summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/mruby/doc/guides/compile.md
blob: 2aaf6f1fec02c2d14dd8d9adc3643f637d791f6d (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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# Compile

mruby uses Rake to compile and cross-compile all libraries and
binaries.

## Prerequisites

To compile mruby out of the source code you need the following tools:
* C Compiler (i.e. ```gcc```)
* Linker (i.e. ```gcc```)
* Archive utility (i.e. ```ar```)
* Parser generator (i.e. ```bison```)
* Ruby 1.8 or 1.9 (i.e. ```ruby``` or ```jruby```)

Optional:
* GIT (to update mruby source and integrate mrbgems easier)
* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
* Assembler (to use GEMs which include \*.asm)

## Usage

Inside of the root directory of the mruby source a file exists
called *build_config.rb*. This file contains the build configuration
of mruby and looks like this for example:
```ruby
MRuby::Build.new do |conf|
  toolchain :gcc
end
```

All tools necessary to compile mruby can be set or modified here. In case
you want to maintain an additional *build_config.rb* you can define a
customized path using the *$MRUBY_CONFIG* environment variable.

To compile just call ```./minirake``` inside of the mruby source root. To
generate and execute the test tools call ```./minirake test```. To clean
all build files call ```./minirake clean```. To see full command line on
build, call ```./minirake -v```.

## Build Configuration

Inside of the *build_config.rb* the following options can be configured
based on your environment.

### Toolchains

The mruby build system already contains a set of toolchain templates which
configure the build environment for specific compiler infrastructures.

#### GCC

Toolchain configuration for the GNU C Compiler.
```ruby
toolchain :gcc
```

#### clang

Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the
GCC toolchain.
```ruby
toolchain :clang
```

#### Visual Studio 2010, 2012 and 2013

Toolchain configuration for Visual Studio on Windows. If you use the
[Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx),
you normally do not have to specify this manually, since it gets automatically detected by our build process.
```ruby
toolchain :visualcpp
```

#### Android

Toolchain configuration for Android.
```ruby
toolchain :android
```

Requires the custom standalone Android NDK and the toolchain path
in ```ANDROID_STANDALONE_TOOLCHAIN```.

### Binaries

It is possible to select which tools should be compiled during the compilation
process. The following tools can be selected:
* mruby (mruby interpreter)
* mirb (mruby interactive shell)

To select them declare conf.gem as follows:
```ruby
conf.gem "#{root}/mrbgems/mruby-bin-mruby"
conf.gem "#{root}/mrbgems/mruby-bin-mirb"
```

### File Separator

Some environments require a different file separator character. It is possible to
set the character via ```conf.file_separator```.
```ruby
conf.file_separator = '/'
```

### C Compiler

Configuration of the C compiler binary, flags and include paths.
```ruby
conf.cc do |cc|
  cc.command = ...
  cc.flags = ...
  cc.include_paths = ...
  cc.defines = ...
  cc.option_include_path = ...
  cc.option_define = ...
  cc.compile_options = ...
end
```

C Compiler has header searcher to detect installed library.

If you need a include path of header file use ```search_header_path```:
```ruby
# Searches ```iconv.h```.
# If found it will return include path of the header file.
# Otherwise it will return nil .
fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h'
```

If you need a full file name of header file use ```search_header```:
```ruby
# Searches ```iconv.h```.
# If found it will return full path of the header file.
# Otherwise it will return nil .
iconv_h = conf.cc.search_header 'iconv.h'
print "iconv.h found: #{iconv_h}\n"
```

Header searcher uses compiler's ```include_paths``` by default.
When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain)
it will use compiler specific include paths too. (For example ```/usr/local/include```, ```/usr/include```)

If you need a special header search paths define a singleton method ```header_search_paths``` to C compiler:
```ruby
def conf.cc.header_search_paths
  ['/opt/local/include'] + include_paths
end
```

### Linker

Configuration of the Linker binary, flags and library paths.
```ruby
conf.linker do |linker|
  linker.command = ...
  linker.flags = ...
  linker.flags_before_libraries = ...
  linker.libraries = ...
  linker.flags_after_libraries = ...
  linker.library_paths = ....
  linker.option_library = ...
  linker.option_library_path = ...
  linker.link_options = ...
end
```

### Archiver

Configuration of the Archiver binary and flags.
```ruby
conf.archiver do |archiver|
  archiver.command = ...
  archiver.archive_options = ...
end
```

### Parser Generator

Configuration of the Parser Generator binary and flags.
```ruby
conf.yacc do |yacc|
  yacc.command = ...
  yacc.compile_options = ...
end
```

### GPerf

Configuration of the GPerf binary and flags.
```ruby
conf.gperf do |gperf|
  gperf.command = ...
  gperf.compile_options = ...
end
```

### File Extensions
```ruby
conf.exts do |exts|
  exts.object = ...
  exts.executable = ...
  exts.library = ...
end
```

### Mrbgems

Integrate GEMs in the build process.
```ruby
# Integrate GEM with additional configuration
conf.gem 'path/to/gem' do |g|
  g.cc.flags << ...
end

# Integrate GEM without additional configuration
conf.gem 'path/to/another/gem'
```

See doc/mrbgems/README.md for more option about mrbgems.

### Mrbtest

Configuration Mrbtest build process.

If you want mrbtest.a only, You should set ```conf.build_mrbtest_lib_only```
```ruby
conf.build_mrbtest_lib_only
```

### Bintest

Tests for mrbgem tools using CRuby.
To have bintests place \*.rb scripts to ```bintest/``` directory of mrbgems.
See ```mruby-bin-*/bintest/*.rb``` if you need examples.
If you want a temporary files use `tempfile` module of CRuby instead of ```/tmp/```.

You can enable it with following:
```ruby
conf.enable_bintest
```

### C++ ABI

By default, mruby uses setjmp/longjmp to implement its
exceptions. But it doesn't release C++ stack object
correctly. To support mrbgems written in C++, mruby can be
configured to use C++ exception.

There are two levels of C++ exception handling. The one is
```enable_cxx_exception``` that enables C++ exception, but
uses C ABI. The other is ```enable_cxx_abi``` where all
files are compiled by C++ compiler.

When you mix C++ code, C++ exception would be enabled automatically.
If you need to enable C++ exception explicitly add the following:
```ruby
conf.enable_cxx_exception
```

#### C++ exception disabling.

If your compiler does not support C++ and you want to ensure
you don't use mrbgem written in C++, you can explicitly disable
C++ exception, add following:
```ruby
conf.disable_cxx_exception
```
and you will get an error when you try to use C++ gem.
Note that it must be called before ```enable_cxx_exception``` or ```gem``` method.

### Debugging mode

To enable debugging mode add the following:
```ruby
conf.enable_debug
```

When debugging mode is enabled
* Macro ```MRB_DEBUG``` would be defined.
	* Which means ```mrb_assert()``` macro is enabled.
* Debug information of irep would be generated by ```mrbc```.
	* Because ```-g``` flag would be added to ```mrbc``` runner.
    * You can have better backtrace of mruby scripts with this.

## Cross-Compilation

mruby can also be cross-compiled from one platform to another. To
achieve this the *build_config.rb* needs to contain an instance of
```MRuby::CrossBuild```. This instance defines the compilation
tools and flags for the target platform. An example could look
like this:
```ruby
MRuby::CrossBuild.new('32bit') do |conf|
  toolchain :gcc

  conf.cc.flags << "-m32"
  conf.linker.flags << "-m32"
end
```

All configuration options of ```MRuby::Build``` can also be used
in ```MRuby::CrossBuild```.

### Mrbtest in Cross-Compilation

In cross compilation, you can run ```mrbtest``` on emulator if
you have it by changing configuration of test runner.
```ruby
conf.test_runner do |t|
  t.command = ... # set emulator. this value must be non nil or false
  t.flags = ... # set flags of emulator

  def t.run(bin) # override `run` if you need to change the behavior of it
    ... # `bin` is the full path of mrbtest
  end
end
```

## Build process

During the build process the directory *build* will be created in the
root directory. The structure of this directory will look like this:

	+- build
	   |
	   +-  host
	       |
	       +- bin          <- Binaries (mirb, mrbc and mruby)
	       |
	       +- lib          <- Libraries (libmruby.a and libmruby_core.a)
	       |
	       +- mrblib
	       |
	       +- src
	       |
	       +- test         <- mrbtest tool
	       |
	       +- tools
	          |
	          +- mirb
	          |
	          +- mrbc
	          |
	          +- mruby

The compilation workflow will look like this:
* compile all files under *src* (object files will be stored
in *build/host/src*)
* generate parser grammar out of *src/parse.y* (generated
result will be stored in *build/host/src/y.tab.c*)
* compile  *build/host/src/y.tab.c* to  *build/host/src/y.tab.o*
* create *build/host/lib/libmruby_core.a* out of all object files (C only)
* create ```build/host/bin/mrbc``` by compiling *tools/mrbc/mrbc.c* and
linking with *build/host/lib/libmruby_core.a*
* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files
under *mrblib* with ```build/host/bin/mrbc```
* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
* create *build/host/lib/libmruby.a* out of all object files (C and Ruby)
* create ```build/host/bin/mruby``` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
linking with *build/host/lib/libmruby.a*
* create ```build/host/bin/mirb``` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
linking with *build/host/lib/libmruby.a*

```
 _____    _____    ______    ____    ____    _____    _____    ____
| CC  |->|GEN  |->|AR    |->|CC  |->|CC  |->|AR   |->|CC   |->|CC  |
| *.c |  |y.tab|  |core.a|  |mrbc|  |*.rb|  |lib.a|  |mruby|  |mirb|
 -----    -----    ------    ----    ----    -----    -----    ----
```

### Cross-Compilation

In case of a cross-compilation to *i386* the *build* directory structure looks
like this:

	+- build
	   |
	   +-  host
	   |   |
	   |   +- bin           <- Native Binaries
	   |   |
	   |   +- lib           <- Native Libraries
	   |   |
	   |   +- mrblib
	   |   |
	   |   +- src
	   |   |
	   |   +- test          <- Native mrbtest tool
	   |   |
	   |   +- tools
	   |      |
	   |      +- mirb
	   |      |
	   |      +- mrbc
	   |      |
	   |      +- mruby
	   +- i386
	      |
	      +- bin            <- Cross-compiled Binaries
	      |
	      +- lib            <- Cross-compiled Libraries
	      |
	      +- mrblib
	      |
	      +- src
	      |
	      +- test           <- Cross-compiled mrbtest tool
	      |
	      +- tools
	         |
	         +- mirb
	         |
	         +- mrbc
	         |
	         +- mruby

An extra directory is created for the target platform. In case you
compile for *i386* a directory called *i386* is created under the
build directory.

The cross compilation workflow starts in the same way as the normal
compilation by compiling all *native* libraries and binaries.
Afterwards the cross compilation process proceeds like this:
* cross-compile all files under *src* (object files will be stored
in *build/i386/src*)
* generate parser grammar out of *src/parse.y* (generated
result will be stored in *build/i386/src/y.tab.c*)
* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o*
* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files
under *mrblib* with the native ```build/host/bin/mrbc```
* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby)
* create ```build/i386/bin/mruby``` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
linking with *build/i386/lib/libmruby.a*
* create ```build/i386/bin/mirb``` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
linking with *build/i386/lib/libmruby.a*
* create *build/i386/lib/libmruby_core.a* out of all object files (C only)
* create ```build/i386/bin/mrbc``` by cross-compiling *tools/mrbc/mrbc.c* and
linking with *build/i386/lib/libmruby_core.a*

```
 _______________________________________________________________
|              Native Compilation for Host System               |
|  _____      ______      _____      ____      ____      _____  |
| | CC  | -> |AR    | -> |GEN  | -> |CC  | -> |CC  | -> |AR   | |
| | *.c |    |core.a|    |y.tab|    |mrbc|    |*.rb|    |lib.a| |
|  -----      ------      -----      ----      ----      -----  |
 ---------------------------------------------------------------
                                ||
                               \||/
                                \/
 ________________________________________________________________
|             Cross Compilation for Target System                |
|  _____      _____      _____      ____      ______      _____  |
| | CC  | -> |AR   | -> |CC   | -> |CC  | -> |AR    | -> |CC   | |
| | *.c |    |lib.a|    |mruby|    |mirb|    |core.a|    |mrbc | |
|  -----      -----      -----      ----      ------      -----  |
 ----------------------------------------------------------------
```

## Build Configuration Examples

### Minimal Library

To build a minimal mruby library you need to use the Cross Compiling
feature due to the reason that there are functions (i.e. stdio) which
can't be disabled for the main build.

```ruby
MRuby::CrossBuild.new('Minimal') do |conf|
  toolchain :gcc

  conf.cc.defines = %w(MRB_DISABLE_STDIO)
  conf.bins = []
end
```

This configuration defines a cross compile build called 'Minimal' which
is using the GCC and compiles for the host machine. It also disables
all usages of stdio and doesn't compile any binaries (i.e. mrbc).

## Test Environment

mruby's build process includes a test environment. In case you start the testing
of mruby, a native binary called ```mrbtest``` will be generated and executed.
This binary contains all test cases which are defined under *test/t*. In case
of a cross-compilation an additional cross-compiled *mrbtest* binary is
generated. You can copy this binary and run on your target system.