ucl 0.1.3.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d2c681a7a148565a2c6e3290750619dfbb43e8c7cea4b0caad20787a22c0f15
4
- data.tar.gz: 2a15c402216b1d7549c93f295e958db3176bfb4455b15d8189885e6c4792f31a
3
+ metadata.gz: c42a6b4100d7e40d367f9328f9d3a34aef3269daf8c8c41a10b88488cc4c5317
4
+ data.tar.gz: 960751a96ec18a4edb15ad341c0c6d9cdc3736d43d2fc67fb33aecfa6855afac
5
5
  SHA512:
6
- metadata.gz: 3b108e5921edbbdf48b232a7fb67a2dc65335c06ee709e74cbfd22ae1900c51ed6cc5ce61928035e0bf6c3e7ebea6dd9570412fc0cbab668caee0d04c61f72d5
7
- data.tar.gz: bf43bcdb042f0e62e5e47d1bfacf7357de3c0262e8e6bda3a15249ba54d63018dc7ec80f0d2eca276088a6745285bb60c1b0b08d678786ecf3945340986bb854
6
+ metadata.gz: a47ad9b9b5ab638c6b957bfcad4044f91bd252343ae8630bd035efc4ac82fb668dbeef27efa29995a4e467372017f8233c9e1c99e8f79a380193bca5a252b144
7
+ data.tar.gz: 11e52d228e3c71d9ef3a9e1415ac724996ea0f2531fb431f5ea8e4b4361cf981630a2d50c3eee04d40f85464b2a50c00a7592579a495d523e0bbe4569f90ebc4
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Stéphane D'Alu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,161 @@
1
+ # Bundled Dependency Licences
2
+
3
+ The `ucl` gem itself is MIT-licensed (see `LICENSE`). Built against a
4
+ system-wide libucl, that is the whole story: nothing here is distributed.
5
+
6
+ When no system libucl is found, the gem compiles the bundled copy in
7
+ `ext/libucl` (a git submodule pinned to an upstream release tag) into the
8
+ extension, and so redistributes the sources below. All are permissive and
9
+ non-copyleft; each asks only that its notice be retained. Every file keeps
10
+ its original header, and the texts are reproduced here so they travel with a
11
+ compiled (binary) distribution too -- what the BSD-2-Clause binary clause
12
+ requires.
13
+
14
+ | Component | Licence | Copyright | Files |
15
+ |---|---|---|---|
16
+ | libucl | BSD-2-Clause | Vsevolod Stakhov | `ext/libucl/src/ucl_*.{c,h}`, `ext/libucl/include/ucl.h`, `ext/libucl/COPYING` |
17
+ | uthash (uthash.h, utlist.h, utstring.h) | BSD-1-Clause | Troy D. Hanson | `ext/libucl/uthash/*.h` |
18
+ | klib (khash.h, kvec.h) | MIT | Attractive Chaos | `ext/libucl/klib/*.h` |
19
+ | mum hash (mum.h) | MIT | Vladimir Makarov | `ext/libucl/src/mum.h` |
20
+ | tree.h (AVL trees) | MIT-style, no sublicence clause | Ian Piumarta | `ext/libucl/src/tree.h` |
21
+
22
+
23
+ ## Licence texts
24
+
25
+ ### libucl
26
+
27
+ BSD-2-Clause
28
+
29
+ ```
30
+ Copyright (c) 2013-2014, Vsevolod Stakhov <vsevolod@highsecure.ru>
31
+ All rights reserved.
32
+
33
+ Redistribution and use in source and binary forms, with or without
34
+ modification, are permitted provided that the following conditions are met:
35
+
36
+ * Redistributions of source code must retain the above copyright notice, this
37
+ list of conditions and the following disclaimer.
38
+
39
+ * Redistributions in binary form must reproduce the above copyright notice,
40
+ this list of conditions and the following disclaimer in the documentation
41
+ and/or other materials provided with the distribution.
42
+
43
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
44
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
46
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
47
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
49
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
50
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
51
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53
+ ```
54
+
55
+ ### uthash (uthash.h, utlist.h, utstring.h)
56
+
57
+ BSD-1-Clause
58
+
59
+ ```
60
+ Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
61
+ All rights reserved.
62
+
63
+ Redistribution and use in source and binary forms, with or without
64
+ modification, are permitted provided that the following conditions are met:
65
+
66
+ Redistributions of source code must retain the above copyright
67
+ notice, this list of conditions and the following disclaimer.
68
+
69
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
70
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
71
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
72
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
73
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
74
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
75
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
76
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
77
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
78
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
79
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
80
+ ```
81
+
82
+ ### klib (khash.h, kvec.h)
83
+
84
+ MIT
85
+
86
+ ```
87
+ The MIT License
88
+
89
+ Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
90
+
91
+ Permission is hereby granted, free of charge, to any person obtaining
92
+ a copy of this software and associated documentation files (the
93
+ "Software"), to deal in the Software without restriction, including
94
+ without limitation the rights to use, copy, modify, merge, publish,
95
+ distribute, sublicense, and/or sell copies of the Software, and to
96
+ permit persons to whom the Software is furnished to do so, subject to
97
+ the following conditions:
98
+
99
+ The above copyright notice and this permission notice shall be
100
+ included in all copies or substantial portions of the Software.
101
+
102
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
103
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
104
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
105
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
106
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
107
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
108
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
109
+ SOFTWARE.
110
+ ```
111
+
112
+ ### mum hash (mum.h)
113
+
114
+ MIT
115
+
116
+ ```
117
+ Copyright (c) 2016 Vladimir Makarov <vmakarov@gcc.gnu.org>
118
+
119
+ Permission is hereby granted, free of charge, to any person
120
+ obtaining a copy of this software and associated documentation
121
+ files (the "Software"), to deal in the Software without
122
+ restriction, including without limitation the rights to use, copy,
123
+ modify, merge, publish, distribute, sublicense, and/or sell copies
124
+ of the Software, and to permit persons to whom the Software is
125
+ furnished to do so, subject to the following conditions:
126
+
127
+ The above copyright notice and this permission notice shall be
128
+ included in all copies or substantial portions of the Software.
129
+
130
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
131
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
132
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
133
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
134
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
135
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
136
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
137
+ SOFTWARE.
138
+ ```
139
+
140
+ ### tree.h (AVL trees)
141
+
142
+ MIT-style. Note it grants no sublicence right and asks that the notice
143
+ appear in supporting documentation -- which this file provides.
144
+
145
+ ```
146
+ Copyright (c) 2005 Ian Piumarta
147
+
148
+ All rights reserved.
149
+
150
+ Permission is hereby granted, free of charge, to any person obtaining a copy
151
+ of this software and associated documentation files (the 'Software'), to deal
152
+ in the Software without restriction, including without limitation the rights
153
+ to use, copy, modify, merge, publish, distribute, and/or sell copies of the
154
+ Software, and to permit persons to whom the Software is furnished to do so,
155
+ provided that the above copyright notice(s) and this permission notice appear
156
+ in all copies of the Software and that both the above copyright notice(s) and
157
+ this permission notice appear in supporting documentation.
158
+
159
+ THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
160
+ ```
161
+
data/README.md ADDED
@@ -0,0 +1,270 @@
1
+ ruby-ucl
2
+ ========
3
+
4
+ Ruby bindings to the [libucl][1] library for parsing configuration files
5
+ written in the **U**niversal **C**onfiguration **L**anguage (UCL).
6
+
7
+ UCL is a configuration format inspired by [nginx][2] and JSON. It is a
8
+ superset of JSON, so any valid JSON document is also valid UCL, while
9
+ adding a more relaxed, human-friendly syntax (unquoted keys, comments,
10
+ optional commas, multipliers, macros, …).
11
+
12
+ Parsed configurations are returned as plain Ruby objects (`Hash`,
13
+ `Array`, `String`, `Integer`, `Float`, `true`/`false`, `nil`), so no
14
+ special object model has to be learned.
15
+
16
+
17
+ Installation
18
+ ------------
19
+
20
+ ~~~sh
21
+ gem install ucl
22
+ ~~~
23
+
24
+ Or add it to your `Gemfile`:
25
+
26
+ ~~~ruby
27
+ gem 'ucl'
28
+ ~~~
29
+
30
+ To track this repository instead of a released gem, **`submodules: true` is
31
+ required**:
32
+
33
+ ~~~ruby
34
+ gem 'ucl', github: 'sdalu/ruby-ucl', submodules: true
35
+ ~~~
36
+
37
+ libucl is vendored as a git submodule (see below), and Bundler does not fetch
38
+ submodules unless asked. Without that option `ext/libucl` stays empty and the
39
+ build fails — except on a machine that happens to have a system-wide libucl,
40
+ where it quietly links against that instead, and only fails once it is
41
+ deployed somewhere that has none.
42
+
43
+ The extension binds to the native [libucl][1] library. At build time it is
44
+ resolved as follows:
45
+
46
+ 1. If a system-wide libucl is found (via `pkg-config`, or under `/opt` or
47
+ `/usr/local`), the extension links against it.
48
+ 2. Otherwise the copy bundled with the gem is compiled directly into the
49
+ extension. This needs nothing but a C compiler — no network access, no
50
+ `cmake`, no extra gems.
51
+
52
+ You can force the bundled copy regardless of any system installation:
53
+
54
+ ~~~sh
55
+ gem install ucl -- --enable-vendor-libucl
56
+ # or, with Bundler:
57
+ bundle config set build.ucl --enable-vendor-libucl
58
+ ~~~
59
+
60
+ Building the bundled copy also compiles out `.include` over http/ftp, which
61
+ is gated on libucl's optional fetch support. A system-wide libucl may have it
62
+ enabled — see [Untrusted input](#untrusted-input).
63
+
64
+ > **Debian/Ubuntu note:** do **not** `apt install libucl-dev`. That package
65
+ > is an unrelated [UCL *data-compression* library][3] that merely shares the
66
+ > name — it does not provide `ucl_parser_new`. The configuration parser is
67
+ > not packaged for Debian, so just let the gem build its bundled copy — a C
68
+ > compiler is all you need. (The parser *is* packaged on Fedora, Homebrew and
69
+ > FreeBSD ports as `libucl`.)
70
+
71
+
72
+ Usage
73
+ -----
74
+
75
+ ~~~ruby
76
+ require 'ucl'
77
+
78
+ # Parse a string of UCL data
79
+ UCL.parse(File.read('foo.conf'))
80
+
81
+ # Same, with macros disabled -- use this for input you do not control
82
+ UCL.safe_parse(untrusted_string)
83
+
84
+ # Parse a file directly (enables file-relative variables such as $FILENAME)
85
+ UCL.load_file('foo.conf')
86
+
87
+ # Pass flags explicitly (combine them with a bitwise OR)
88
+ UCL.load_file('foo.conf', UCL::KEY_SYMBOL | UCL::KEY_LOWERCASE)
89
+
90
+ # Or set the default flags applied to every subsequent call
91
+ UCL.flags = UCL::KEY_SYMBOL
92
+ UCL.parse('name = value') #=> { :name => "value" }
93
+ ~~~
94
+
95
+ Both `parse` and `load_file` accept an optional `flags` argument. When it
96
+ is omitted, the value of `UCL.flags` (default: no flag) is used.
97
+ `UCL.safe_parse` takes the same arguments as `parse` and always adds
98
+ `UCL::DISABLE_MACRO` (see *Untrusted input* below).
99
+
100
+ On a malformed configuration, or if conversion of the parsed tree fails,
101
+ a `UCL::Error` is raised.
102
+
103
+ Given a configuration like:
104
+
105
+ ~~~nginx
106
+ # a sample configuration
107
+ name = example
108
+ # timeout is parsed as a number of seconds, max_size understands multipliers
109
+ timeout = 30s
110
+ max_size = 10mb
111
+
112
+ servers = [
113
+ { host = a.example, port = 8080 },
114
+ { host = b.example, port = 8081 },
115
+ ]
116
+
117
+ logging {
118
+ level = info
119
+ enabled = yes
120
+ }
121
+ ~~~
122
+
123
+ `UCL.load_file` returns:
124
+
125
+ ~~~ruby
126
+ {
127
+ "name" => "example",
128
+ "timeout" => 30.0,
129
+ "max_size" => 10485760,
130
+ "servers" => [ { "host" => "a.example", "port" => 8080 },
131
+ { "host" => "b.example", "port" => 8081 } ],
132
+ "logging" => { "level" => "info", "enabled" => true },
133
+ }
134
+ ~~~
135
+
136
+
137
+ Flags
138
+ -----
139
+
140
+ | Flag | Effect |
141
+ |------------------|---------------------------------------------------------------|
142
+ | `KEY_SYMBOL` | Return object keys as `Symbol` instead of `String`. |
143
+ | `KEY_LOWERCASE` | Convert all keys to lower case. |
144
+ | `NO_TIME` | Do not parse time values; keep them as strings. |
145
+ | `DISABLE_MACRO` | Disable processing of macros (e.g. `.include`); see *Untrusted input*. |
146
+ | `NO_FILEVARS` | Do not predefine `$FILENAME` / `$CURDIR` (affects `parse`; `load_file` still sets them from the file). |
147
+
148
+
149
+ Untrusted input
150
+ ---------------
151
+
152
+ `UCL.parse` and `UCL.load_file` process macros, so a configuration can pull
153
+ in other files through `.include`:
154
+
155
+ ~~~ruby
156
+ UCL.parse('.include "/etc/secrets.conf"')
157
+ #=> the contents of that file, as Ruby objects
158
+ ~~~
159
+
160
+ That is a feature of the format — it is how a configuration is split across
161
+ several files — but it means **a configuration string from an untrusted
162
+ source can read any file the process can read**. Parse such input with
163
+ `UCL.safe_parse`, which is `UCL.parse` with `UCL::DISABLE_MACRO` always
164
+ added:
165
+
166
+ ~~~ruby
167
+ UCL.safe_parse(params[:config]) # `.include` is not executed
168
+ ~~~
169
+
170
+ `load_file` has no `safe_` counterpart: the path comes from the caller, so
171
+ the decision to trust the file has already been made. Pass
172
+ `UCL::DISABLE_MACRO` explicitly if a trusted path holds untrusted content.
173
+
174
+ If libucl was built with URL includes enabled (the bundled build disables
175
+ them; a system-wide libucl may not), `.include` can also fetch over the
176
+ network. One more reason to reach for `safe_parse`.
177
+
178
+
179
+ Limits
180
+ ------
181
+
182
+ Objects nested more than **1000 levels** deep are rejected with a
183
+ `UCL::Error`. Converting the parsed tree recurses once per level, as does
184
+ libucl's own handling of it, so an unbounded depth would exhaust the C
185
+ stack — a 1 MiB thread stack (what a Puma or Sidekiq worker gets) is gone
186
+ at roughly 15000 levels. Real configurations nest a handful of levels;
187
+ Ruby's own JSON parser stops at 100.
188
+
189
+ > **Known limitation.** The check happens when the parsed tree is converted,
190
+ > which is too late for input that is *both* deeply nested *and* malformed:
191
+ > libucl then releases its half-built tree recursively from inside
192
+ > `ucl_parser_free()`, out of reach of this binding, and a document such as
193
+ > `'a = ' + '[' * 20_000` raises `SystemStackError` instead of `UCL::Error`
194
+ > and leaks the parser. Deeply nested *well-formed* input is handled
195
+ > correctly. If you parse untrusted configurations, cap their size.
196
+
197
+
198
+ Type mapping
199
+ ------------
200
+
201
+ | UCL type | Ruby type |
202
+ |------------|--------------------------|
203
+ | object | `Hash` |
204
+ | array | `Array` |
205
+ | string | `String` |
206
+ | integer | `Integer` |
207
+ | float | `Float` |
208
+ | time | `Float` (seconds) |
209
+ | boolean | `true` / `false` |
210
+ | null | `nil` |
211
+
212
+ Notes:
213
+
214
+ * The parser uses explicit (not implicit) arrays, so a key repeated several
215
+ times is collected into an `Array` of its values:
216
+
217
+ ~~~ruby
218
+ UCL.parse("a = 1\na = 2") #=> { "a" => [1, 2] }
219
+ UCL.parse("a = 1") #=> { "a" => 1 }
220
+ ~~~
221
+
222
+ * Integers understand size multipliers (`1k` → 1000, `1kb` → 1024,
223
+ `1mb` → 1048576), hexadecimal (`0x1f` → 31) and JSON is accepted as-is.
224
+
225
+ * **A trailing `#` comment suppresses suffix parsing.** `t = 30s` is the
226
+ float `30.0` and `n = 10mb` the integer `10485760`, but `t = 30s # note`
227
+ and `n = 10mb # note` come back as the *strings* `"30s"` and `"10mb"`.
228
+ Plain integers and floats are unaffected (`n = 1 # note` is `1`). This is
229
+ libucl's behaviour, not the binding's; put the comment on its own line
230
+ when the value carries a unit or a multiplier.
231
+
232
+ * Returned strings carry their verbatim bytes but are tagged with the
233
+ `ASCII-8BIT` (binary) encoding; call `String#force_encoding('UTF-8')` if
234
+ you need them as UTF-8.
235
+
236
+
237
+ Development
238
+ -----------
239
+
240
+ ~~~sh
241
+ git submodule update --init # populate ext/libucl (bundled libucl sources)
242
+ bundle install # install development dependencies
243
+ rake compile # build the C extension into ext/
244
+ rake test # compile and run the test suite
245
+ rake clobber # remove all generated files
246
+ ~~~
247
+
248
+ `rake test` works with the development gems installed system-wide too; with
249
+ a `Gemfile.lock` present, prefix commands with `bundle exec`.
250
+
251
+ `ext/libucl` is a git submodule pinned to an upstream release tag; `rake
252
+ compile` and `rake build` both refuse to run until it is populated. To move
253
+ to a newer libucl, check out the new tag inside it and commit the pointer.
254
+
255
+
256
+ License
257
+ -------
258
+
259
+ Released under the MIT License. See [LICENSE](LICENSE).
260
+
261
+ When built against a system-wide libucl, nothing else is distributed. When
262
+ the bundled copy is compiled in, the gem also redistributes libucl and the
263
+ libraries vendored inside it (uthash, klib, mum, tree.h) — all permissive,
264
+ all notice-retention only. Their texts are in
265
+ [LICENSE-DEPENDENCIES.md](LICENSE-DEPENDENCIES.md).
266
+
267
+
268
+ [1]: https://github.com/vstakhov/libucl
269
+ [2]: https://nginx.org/
270
+ [3]: https://www.oberhumer.com/opensource/ucl/
data/ext/extconf.rb CHANGED
@@ -1,7 +1,71 @@
1
1
  require 'mkmf'
2
2
 
3
+ # Vendored libucl (vstakhov's Universal Configuration Language parser), used
4
+ # when no system-wide installation is found. It lives in ext/libucl, a git
5
+ # submodule pinned to a release tag. NOTE: this is *not* the Debian
6
+ # `libucl-dev` package, which is an unrelated compression library.
7
+ #
8
+ # Its sources are compiled straight into this extension rather than built as a
9
+ # separate library: src/ucl_internal.h defines the HAVE_* macros itself when
10
+ # HAVE_CONFIG_H is absent -- upstream calls this the "embedded build" and ships
11
+ # a Makefile.unix for it -- so no configure step is needed, and with it go the
12
+ # download, cmake, and any question of which libucl the linker picks up.
13
+ #
14
+ # One useful side effect: `.include` over http/ftp is gated on HAVE_FETCH_H and
15
+ # CURL_H, which the embedded build never defines, so remote includes are
16
+ # compiled out. A system-wide libucl may well have them enabled.
17
+ LIBUCL_DIR = File.join(__dir__, 'libucl').freeze
3
18
 
4
- find_library('ucl', 'ucl_parser_new', '/opt/lib')
5
- find_header('ucl.h', '/opt/include')
19
+ # Force using the bundled copy, ignoring any system installation:
20
+ # gem install ucl -- --enable-vendor-libucl
21
+ # bundle config set build.ucl --enable-vendor-libucl
22
+ # UCL_VENDOR_LIBUCL=1 rake compile
23
+ force_vendor = enable_config('vendor-libucl', false) ||
24
+ ENV.key?('UCL_VENDOR_LIBUCL')
6
25
 
7
- create_makefile("ucl")
26
+ # Locate a system-wide libucl: pkg-config first, then the usual prefixes.
27
+ def system_libucl
28
+ return true if pkg_config('libucl')
29
+
30
+ find_header( 'ucl.h', '/opt/include', '/usr/local/include') &&
31
+ find_library('ucl', 'ucl_parser_new', '/opt/lib', '/usr/local/lib')
32
+ end
33
+
34
+ # The submodule is not populated in a fresh clone, and a gem packaged without
35
+ # it would fail here rather than at `git submodule update` time.
36
+ def bundled_libucl
37
+ File.exist?(File.join(LIBUCL_DIR, 'src', 'ucl_parser.c'))
38
+ end
39
+
40
+ if !force_vendor && system_libucl
41
+ message "Using system libucl.\n"
42
+ else
43
+ unless bundled_libucl
44
+ abort "\nThe bundled libucl sources are missing from #{LIBUCL_DIR}.\n" \
45
+ "In a git checkout, populate the submodule with:\n" \
46
+ " git submodule update --init\n" \
47
+ "In an installed gem this means the gem was packaged without them; " \
48
+ "please report it.\n" \
49
+ "Failing that, install libucl system-wide and build again.\n"
50
+ end
51
+
52
+ # Prepended so that a system-wide ucl.h cannot shadow the bundled one.
53
+ $INCFLAGS = "-I#{LIBUCL_DIR}/include -I#{LIBUCL_DIR}/uthash " \
54
+ "-I#{LIBUCL_DIR}/src -I#{LIBUCL_DIR}/klib #{$INCFLAGS}"
55
+
56
+ # Every .c under src/ -- the same set CMakeLists.txt lists as UCLSRC.
57
+ $srcs = [File.join(__dir__, 'ucl.c')] +
58
+ Dir[File.join(LIBUCL_DIR, 'src', '*.c')].sort
59
+ $objs = $srcs.map { |src| "#{File.basename(src, '.c')}.o" }
60
+ $VPATH << "$(srcdir)/libucl/src"
61
+
62
+ # libucl's own build passes both; without them its sources emit a few hundred
63
+ # warning lines through an unrelated gem's install log.
64
+ $CFLAGS << ' -Wno-pointer-sign -Wno-unused-parameter'
65
+
66
+ have_library('m') # libucl relies on the math library
67
+
68
+ message "Compiling the bundled libucl into the extension.\n"
69
+ end
70
+
71
+ create_makefile('ucl')
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2013-2014, Vsevolod Stakhov <vsevolod@highsecure.ru>
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.