jsonnet 0.1.0 → 0.4.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 +5 -5
- data/.clang-format +11 -0
- data/.travis.yml +19 -0
- data/README.md +72 -13
- data/ext/jsonnet/callbacks.c +241 -0
- data/ext/jsonnet/extconf.rb +56 -0
- data/ext/jsonnet/helpers.c +74 -0
- data/ext/jsonnet/jsonnet.c +4 -357
- data/ext/jsonnet/jsonnet_values.c +206 -0
- data/ext/jsonnet/ruby_jsonnet.h +39 -0
- data/ext/jsonnet/vm.c +508 -0
- data/jsonnet.gemspec +6 -4
- data/lib/jsonnet.rb +42 -2
- data/lib/jsonnet/version.rb +1 -1
- data/lib/jsonnet/vm.rb +127 -8
- data/test/fixtures/jpath.libsonnet +3 -0
- data/test/test_jsonnet.rb +44 -1
- data/test/test_vm.rb +313 -10
- metadata +37 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2872d26e221e6ec8bbd30265edd0109eb9f1c68fa19fcfaa888c9921f096f771
|
4
|
+
data.tar.gz: b91f326aa5a64a97f9f088a17b6462e8cf77d8e82679c11231cc68eff2b495e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dab85234e40a4b05ae60a4fe7423af108df27b9e3d2db119e6d18edb40f9abbb92c20a5cf7c25fb5d20e3a090031fae42ec93fab135ea3c6682adaf3ec006693
|
7
|
+
data.tar.gz: 8aea3bbab4b7661a4ee6d055bd6fdd9b5c0834feae98f266b5d162563b860b932689f4fcd4096a3f2dcdf12fb5e960b2fbb7f7e65ce23d1d177d5f85128dbb56
|
data/.clang-format
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
dist: xenial
|
3
|
+
script: bundle exec rake test
|
4
|
+
|
5
|
+
matrix:
|
6
|
+
include:
|
7
|
+
- os: linux
|
8
|
+
rvm: 2.5.8
|
9
|
+
- os: osx
|
10
|
+
rvm: 2.5.8
|
11
|
+
- os: linux
|
12
|
+
rvm: 2.6.6
|
13
|
+
- os: osx
|
14
|
+
rvm: 2.6.6
|
15
|
+
- os: linux
|
16
|
+
rvm: 2.7.2
|
17
|
+
- os: osx
|
18
|
+
rvm: 2.7.2
|
19
|
+
fast_finish: true
|
data/README.md
CHANGED
@@ -1,17 +1,11 @@
|
|
1
|
+
[](https://travis-ci.org/yugui/ruby-jsonnet)
|
2
|
+
|
1
3
|
# Jsonnet
|
2
4
|
|
3
|
-
Jsonnet processor library. Wraps the official C++ implementation with a Ruby
|
5
|
+
[Jsonnet][] processor library. Wraps the official C++ implementation with a Ruby extension library.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
7
|
-
Install libjsonnet:
|
8
|
-
|
9
|
-
$ git clone https://github.com/google/jsonnet.git
|
10
|
-
$ cd jsonnet
|
11
|
-
$ make
|
12
|
-
$ sudo cp libjsonnet.so /usr/local/lib/libjsonnet.so
|
13
|
-
$ sudo cp libjsonnet.h /usr/local/include/libjsonnet.h
|
14
|
-
|
15
9
|
Add this line to your application's Gemfile:
|
16
10
|
|
17
11
|
```ruby
|
@@ -20,20 +14,85 @@ gem 'jsonnet'
|
|
20
14
|
|
21
15
|
And then execute:
|
22
16
|
|
23
|
-
|
17
|
+
```shell
|
18
|
+
$ bundle install
|
19
|
+
```
|
24
20
|
|
25
21
|
Or install it yourself as:
|
26
22
|
|
27
|
-
|
23
|
+
```shell
|
24
|
+
$ gem install jsonnet
|
25
|
+
```
|
26
|
+
|
27
|
+
By default this gem will compile and install Jsonnet (v0.16.0) as part of
|
28
|
+
installation. However you can use the system version of Jsonnet if you prefer.
|
29
|
+
This would be the recommended route if you want to use a different version
|
30
|
+
of Jsonnet or are having problems installing this.
|
31
|
+
|
32
|
+
To install libjsonnet:
|
33
|
+
|
34
|
+
```shell
|
35
|
+
$ git clone https://github.com/google/jsonnet.git
|
36
|
+
$ cd jsonnet
|
37
|
+
$ make libjsonnet.so
|
38
|
+
$ sudo cp libjsonnet.so /usr/local/lib/libjsonnet.so
|
39
|
+
$ sudo cp include/libjsonnet.h /usr/local/include/libjsonnet.h
|
40
|
+
```
|
41
|
+
|
42
|
+
Note: /usr/local/lib and /usr/local/include are used as they are library lookup
|
43
|
+
locations. You may need to adjust these for your system if you have errors
|
44
|
+
running this gem saying it can't open libjsonnet.so - on Ubuntu for instance
|
45
|
+
I found /lib worked when /usr/local/lib did not.
|
46
|
+
|
47
|
+
To install this gem without jsonnet:
|
48
|
+
|
49
|
+
Use `JSONNET_USE_SYSTEM_LIBRARIES` ENV var:
|
50
|
+
|
51
|
+
```shell
|
52
|
+
$ JSONNET_USE_SYSTEM_LIBRARIES=1 bundle install
|
53
|
+
```
|
54
|
+
|
55
|
+
or, the `--use-system-libraries` option:
|
56
|
+
|
57
|
+
|
58
|
+
```shell
|
59
|
+
gem install jsonnet -- --use-system-libraries
|
60
|
+
```
|
28
61
|
|
29
62
|
## Usage
|
30
63
|
|
31
|
-
|
64
|
+
Load the library with `require "jsonnet"`
|
65
|
+
|
66
|
+
You can evaluate a string of Jsonnet using `Jsonnet.parse`
|
67
|
+
|
68
|
+
```
|
69
|
+
irb(main):002:0> Jsonnet.evaluate('{ foo: "bar" }')
|
70
|
+
=> {"foo"=>"bar"}
|
71
|
+
```
|
72
|
+
Or load a file using `Jsonnet.load`
|
73
|
+
|
74
|
+
```
|
75
|
+
irb(main):002:0> Jsonnet.load('example.jsonnet')
|
76
|
+
=> {"baz"=>1}
|
77
|
+
```
|
78
|
+
|
79
|
+
To get closer to the C++ interface you can create an instance of `Jsonnet::VM`
|
80
|
+
|
81
|
+
```
|
82
|
+
irb(main):002:0> vm = Jsonnet::VM.new
|
83
|
+
=> #<Jsonnet::VM:0x007fd29aa1e568>
|
84
|
+
irb(main):003:0> vm.evaluate('{ foo: "bar" }')
|
85
|
+
=> "{\n \"foo\": \"bar\"\n}\n"
|
86
|
+
irb(main):004:0> vm.evaluate_file('example.jsonnet')
|
87
|
+
=> "{\n \"baz\": 1\n}\n"
|
88
|
+
```
|
32
89
|
|
33
90
|
## Contributing
|
34
91
|
|
35
|
-
1. Fork it ( https://github.com/yugui/jsonnet/fork )
|
92
|
+
1. Fork it ( https://github.com/yugui/ruby-jsonnet/fork )
|
36
93
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
37
94
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
95
|
4. Push to the branch (`git push origin my-new-feature`)
|
39
96
|
5. Create a new Pull Request
|
97
|
+
|
98
|
+
[Jsonnet]: https://github.com/google/jsonnet
|
@@ -0,0 +1,241 @@
|
|
1
|
+
#include <string.h>
|
2
|
+
|
3
|
+
#include <libjsonnet.h>
|
4
|
+
#include <ruby/ruby.h>
|
5
|
+
|
6
|
+
#include "ruby_jsonnet.h"
|
7
|
+
|
8
|
+
/* Magic prefix which distinguishes Ruby-level non-exception global escapes
|
9
|
+
* from other errors in Jsonnet.
|
10
|
+
* Any other errors in Jsonnet evaluation cannot contain this fragment of message.
|
11
|
+
*/
|
12
|
+
#define RUBYJSONNET_GLOBAL_ESCAPE_MAGIC "\x07\x03\x0c:rubytag:\x07\x03\x0c:"
|
13
|
+
|
14
|
+
/*
|
15
|
+
* callback support in VM
|
16
|
+
*/
|
17
|
+
|
18
|
+
static ID id_call;
|
19
|
+
|
20
|
+
/*
|
21
|
+
* Just invokes a callback with arguments, but also adapts the invocation to rb_protect.
|
22
|
+
* @param[in] args list of arguments whose first value is the callable object itself.
|
23
|
+
* @return result of the callback
|
24
|
+
*/
|
25
|
+
static VALUE
|
26
|
+
invoke_callback(VALUE args)
|
27
|
+
{
|
28
|
+
long len = RARRAY_LEN(args);
|
29
|
+
VALUE callback = rb_ary_entry(args, 0);
|
30
|
+
return rb_funcall2(callback, id_call, len - 1, RARRAY_PTR(args) + 1);
|
31
|
+
}
|
32
|
+
|
33
|
+
/*
|
34
|
+
* Handles long jump caught by rb_protect() in a callback function.
|
35
|
+
*
|
36
|
+
* Returns an error message which represents rb_errinfo().
|
37
|
+
* It is the caller's responsibility to return the message to the Jsonnet VM
|
38
|
+
* in the right way.
|
39
|
+
* Also the caller of the VM must handle evaluation failure caused by the
|
40
|
+
* error message.
|
41
|
+
* \sa rubyjsonnet_jump_tag
|
42
|
+
* \sa raise_eval_error
|
43
|
+
*/
|
44
|
+
static VALUE
|
45
|
+
rescue_callback(int state, const char *fmt, ...)
|
46
|
+
{
|
47
|
+
VALUE err = rb_errinfo();
|
48
|
+
if (rb_obj_is_kind_of(err, rb_eException)) {
|
49
|
+
VALUE msg = rb_protect(rubyjsonnet_format_exception, rb_errinfo(), NULL);
|
50
|
+
if (msg == Qnil) {
|
51
|
+
va_list ap;
|
52
|
+
va_start(ap, fmt);
|
53
|
+
msg = rb_vsprintf(fmt, ap);
|
54
|
+
va_end(ap);
|
55
|
+
}
|
56
|
+
rb_set_errinfo(Qnil);
|
57
|
+
return msg;
|
58
|
+
}
|
59
|
+
|
60
|
+
/*
|
61
|
+
* Other types of global escape.
|
62
|
+
* Here, we'll report the state as an evaluation error to let
|
63
|
+
* the Jsonnet VM clean up its internal resources.
|
64
|
+
* But we'll translate the error into an non-exception global escape
|
65
|
+
* in Ruby again in raise_eval_error().
|
66
|
+
*/
|
67
|
+
return rb_sprintf("%s%d%s", RUBYJSONNET_GLOBAL_ESCAPE_MAGIC, state,
|
68
|
+
RUBYJSONNET_GLOBAL_ESCAPE_MAGIC);
|
69
|
+
}
|
70
|
+
|
71
|
+
/*
|
72
|
+
* Tries to extract a jump tag from a string representation encoded by
|
73
|
+
* rescue_callback.
|
74
|
+
* @retval zero if \a exc_mesg is not such a string representation.
|
75
|
+
* @retval non-zero the extracted tag
|
76
|
+
*/
|
77
|
+
int
|
78
|
+
rubyjsonnet_jump_tag(const char *exc_mesg)
|
79
|
+
{
|
80
|
+
const char *tag;
|
81
|
+
#define JSONNET_RUNTIME_ERROR_PREFIX "RUNTIME ERROR: "
|
82
|
+
if (strncmp(exc_mesg, JSONNET_RUNTIME_ERROR_PREFIX, strlen(JSONNET_RUNTIME_ERROR_PREFIX))) {
|
83
|
+
return 0;
|
84
|
+
}
|
85
|
+
tag = strstr(exc_mesg + strlen(JSONNET_RUNTIME_ERROR_PREFIX), RUBYJSONNET_GLOBAL_ESCAPE_MAGIC);
|
86
|
+
if (tag) {
|
87
|
+
const char *const body = tag + strlen(RUBYJSONNET_GLOBAL_ESCAPE_MAGIC);
|
88
|
+
char *last;
|
89
|
+
long state = strtol(body, &last, 10);
|
90
|
+
if (!strncmp(last, RUBYJSONNET_GLOBAL_ESCAPE_MAGIC,
|
91
|
+
strlen(RUBYJSONNET_GLOBAL_ESCAPE_MAGIC)) &&
|
92
|
+
INT_MIN <= state && state <= INT_MAX) {
|
93
|
+
return (int)state;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
return 0;
|
97
|
+
}
|
98
|
+
|
99
|
+
static char *
|
100
|
+
import_callback_entrypoint(void *ctx, const char *base, const char *rel, char **found_here,
|
101
|
+
int *success)
|
102
|
+
{
|
103
|
+
struct jsonnet_vm_wrap *const vm = (struct jsonnet_vm_wrap *)ctx;
|
104
|
+
int state;
|
105
|
+
VALUE result, args;
|
106
|
+
|
107
|
+
args = rb_ary_tmp_new(3);
|
108
|
+
|
109
|
+
rb_ary_push(args, vm->import_callback);
|
110
|
+
rb_ary_push(args, rb_enc_str_new_cstr(base, rb_filesystem_encoding()));
|
111
|
+
rb_ary_push(args, rb_enc_str_new_cstr(rel, rb_filesystem_encoding()));
|
112
|
+
result = rb_protect(invoke_callback, args, &state);
|
113
|
+
|
114
|
+
rb_ary_free(args);
|
115
|
+
|
116
|
+
if (state) {
|
117
|
+
VALUE msg = rescue_callback(state, "cannot import %s from %s", rel, base);
|
118
|
+
*success = 0;
|
119
|
+
return rubyjsonnet_str_to_cstr(vm->vm, msg);
|
120
|
+
}
|
121
|
+
|
122
|
+
result = rb_Array(result);
|
123
|
+
*success = 1;
|
124
|
+
*found_here = rubyjsonnet_str_to_cstr(vm->vm, rb_ary_entry(result, 1));
|
125
|
+
return rubyjsonnet_str_to_cstr(vm->vm, rb_ary_entry(result, 0));
|
126
|
+
}
|
127
|
+
|
128
|
+
/*
|
129
|
+
* Sets a custom way to resolve "import" expression.
|
130
|
+
* @param [#call] callback receives two parameters and returns two values.
|
131
|
+
* The first parameter "base" is a base directory to resolve
|
132
|
+
* "rel" from.
|
133
|
+
* The second parameter "rel" is an absolute or a relative
|
134
|
+
* path to the file to import.
|
135
|
+
* The first return value is the content of the imported file.
|
136
|
+
* The second return value is the resolved path of the imported file.
|
137
|
+
*/
|
138
|
+
static VALUE
|
139
|
+
vm_set_import_callback(VALUE self, VALUE callback)
|
140
|
+
{
|
141
|
+
struct jsonnet_vm_wrap *const vm = rubyjsonnet_obj_to_vm(self);
|
142
|
+
|
143
|
+
vm->import_callback = callback;
|
144
|
+
jsonnet_import_callback(vm->vm, import_callback_entrypoint, vm);
|
145
|
+
|
146
|
+
return callback;
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Generic entrypoint of native callbacks which adapts callable objects in Ruby to \c
|
151
|
+
* JsonnetNativeCallback.
|
152
|
+
*
|
153
|
+
* @param[in] data pointer to a {\c struct native_callback_ctx}
|
154
|
+
* @param[in] argv NULL-terminated array of arguments
|
155
|
+
* @param[out] success set to 1 on success, or 0 if otherwise.
|
156
|
+
* @returns the result of the callback on success, an error message on failure.
|
157
|
+
*/
|
158
|
+
static struct JsonnetJsonValue *
|
159
|
+
native_callback_entrypoint(void *data, const struct JsonnetJsonValue *const *argv, int *success)
|
160
|
+
{
|
161
|
+
long i;
|
162
|
+
int state = 0;
|
163
|
+
|
164
|
+
struct native_callback_ctx *const ctx = (struct native_callback_ctx *)data;
|
165
|
+
struct JsonnetVm *const vm = rubyjsonnet_obj_to_vm(ctx->vm)->vm;
|
166
|
+
VALUE result, args = rb_ary_tmp_new(ctx->arity + 1);
|
167
|
+
|
168
|
+
rb_ary_push(args, ctx->callback);
|
169
|
+
for (i = 0; i < ctx->arity; ++i) {
|
170
|
+
rb_ary_push(args, rubyjsonnet_json_to_obj(vm, argv[i]));
|
171
|
+
}
|
172
|
+
|
173
|
+
result = rb_protect(invoke_callback, args, &state);
|
174
|
+
|
175
|
+
rb_ary_free(args);
|
176
|
+
|
177
|
+
if (state) {
|
178
|
+
VALUE msg = rescue_callback(state, "something wrong in %" PRIsVALUE, ctx->callback);
|
179
|
+
*success = 0;
|
180
|
+
return rubyjsonnet_obj_to_json(vm, msg, &state);
|
181
|
+
}
|
182
|
+
|
183
|
+
return rubyjsonnet_obj_to_json(vm, result, success);
|
184
|
+
}
|
185
|
+
|
186
|
+
/*
|
187
|
+
* Registers a native extension written in Ruby.
|
188
|
+
* @param callback [#call] a PURE callable object
|
189
|
+
* @param params [Array] names of the parameters of the function
|
190
|
+
*/
|
191
|
+
static VALUE
|
192
|
+
vm_register_native_callback(VALUE self, VALUE name, VALUE callback, VALUE params)
|
193
|
+
{
|
194
|
+
struct {
|
195
|
+
volatile VALUE store;
|
196
|
+
long len;
|
197
|
+
const char **buf;
|
198
|
+
} cstr_params;
|
199
|
+
struct native_callback_ctx *ctx;
|
200
|
+
struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
|
201
|
+
long i;
|
202
|
+
|
203
|
+
name = rb_to_symbol(name);
|
204
|
+
rubyjsonnet_assert_asciicompat(name);
|
205
|
+
|
206
|
+
params = rb_Array(params);
|
207
|
+
cstr_params.len = RARRAY_LEN(params);
|
208
|
+
cstr_params.buf = (const char **)rb_alloc_tmp_buffer(
|
209
|
+
&cstr_params.store, sizeof(const char *const) * (cstr_params.len + 1));
|
210
|
+
for (i = 0; i < cstr_params.len; ++i) {
|
211
|
+
const VALUE pname = rb_to_symbol(RARRAY_AREF(params, i));
|
212
|
+
rubyjsonnet_assert_asciicompat(pname);
|
213
|
+
cstr_params.buf[i] = rb_id2name(RB_SYM2ID(pname));
|
214
|
+
}
|
215
|
+
cstr_params.buf[cstr_params.len] = NULL;
|
216
|
+
|
217
|
+
ctx = RB_ALLOC_N(struct native_callback_ctx, 1);
|
218
|
+
ctx->callback = callback;
|
219
|
+
ctx->arity = cstr_params.len;
|
220
|
+
ctx->vm = self;
|
221
|
+
jsonnet_native_callback(vm->vm, rb_id2name(RB_SYM2ID(name)), native_callback_entrypoint, ctx,
|
222
|
+
cstr_params.buf);
|
223
|
+
|
224
|
+
rb_free_tmp_buffer(&cstr_params.store);
|
225
|
+
|
226
|
+
RB_REALLOC_N(vm->native_callbacks.contexts, struct native_callback_ctx *,
|
227
|
+
vm->native_callbacks.len + 1);
|
228
|
+
vm->native_callbacks.contexts[vm->native_callbacks.len] = ctx;
|
229
|
+
vm->native_callbacks.len++;
|
230
|
+
|
231
|
+
return name;
|
232
|
+
}
|
233
|
+
|
234
|
+
void
|
235
|
+
rubyjsonnet_init_callbacks(VALUE cVM)
|
236
|
+
{
|
237
|
+
id_call = rb_intern("call");
|
238
|
+
|
239
|
+
rb_define_method(cVM, "import_callback=", vm_set_import_callback, 1);
|
240
|
+
rb_define_private_method(cVM, "register_native_callback", vm_register_native_callback, 3);
|
241
|
+
}
|
data/ext/jsonnet/extconf.rb
CHANGED
@@ -1,6 +1,62 @@
|
|
1
1
|
require 'mkmf'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
def using_system_libraries?
|
5
|
+
arg_config('--use-system-libraries', !!ENV['JSONNET_USE_SYSTEM_LIBRARIES'])
|
6
|
+
end
|
2
7
|
|
3
8
|
dir_config('jsonnet')
|
9
|
+
|
10
|
+
unless using_system_libraries?
|
11
|
+
message "Building jsonnet using packaged libraries.\n"
|
12
|
+
require 'rubygems'
|
13
|
+
require 'mini_portile2'
|
14
|
+
message "Using mini_portile version #{MiniPortile::VERSION}\n"
|
15
|
+
|
16
|
+
recipe = MiniPortile.new('jsonnet', 'v0.17.0')
|
17
|
+
recipe.files = ['https://github.com/google/jsonnet/archive/v0.17.0.tar.gz']
|
18
|
+
class << recipe
|
19
|
+
|
20
|
+
def compile
|
21
|
+
# We want to create a file a library we can link to. Jsonnet provides us
|
22
|
+
# with the command `make libjsonnet.so` which creates a shared object
|
23
|
+
# however that won't be bundled into the compiled output so instead
|
24
|
+
# we compile the c into .o files and then create an archive that can
|
25
|
+
# be linked to
|
26
|
+
execute('compile', make_cmd)
|
27
|
+
execute('archive', 'ar rcs libjsonnet.a core/desugarer.o core/formatter.o core/lexer.o core/libjsonnet.o core/parser.o core/pass.o core/static_analysis.o core/string_utils.o core/vm.o third_party/md5/md5.o')
|
28
|
+
end
|
29
|
+
|
30
|
+
def configured?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def install
|
35
|
+
lib_path = File.join(port_path, 'lib')
|
36
|
+
include_path = File.join(port_path, 'include')
|
37
|
+
|
38
|
+
FileUtils.mkdir_p([lib_path, include_path])
|
39
|
+
|
40
|
+
FileUtils.cp(File.join(work_path, 'libjsonnet.a'), lib_path)
|
41
|
+
FileUtils.cp(File.join(work_path, 'include', 'libjsonnet.h'), include_path)
|
42
|
+
FileUtils.cp(File.join(work_path, 'include', 'libjsonnet_fmt.h'), include_path)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
recipe.cook
|
47
|
+
# I tried using recipe.activate here but that caused this file to build ok
|
48
|
+
# but the makefile to fail. These commands add the necessary paths to do both
|
49
|
+
$LIBPATH = ["#{recipe.path}/lib"] | $LIBPATH
|
50
|
+
$CPPFLAGS << " -I#{recipe.path}/include"
|
51
|
+
|
52
|
+
# This resolves an issue where you can get improper linkage when compiling
|
53
|
+
# and get an error like "undefined symbol: _ZTVN10__cxxabiv121__vmi_class_type_infoE"
|
54
|
+
# experienced on ubuntu.
|
55
|
+
# See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=193950
|
56
|
+
$LIBS << " -lstdc++"
|
57
|
+
end
|
58
|
+
|
4
59
|
abort 'libjsonnet.h not found' unless have_header('libjsonnet.h')
|
5
60
|
abort 'libjsonnet not found' unless have_library('jsonnet')
|
61
|
+
have_header('libjsonnet_fmt.h')
|
6
62
|
create_makefile('jsonnet/jsonnet_wrap')
|