sqlite3 1.5.0 → 2.0.2

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +390 -0
  3. data/CONTRIBUTING.md +34 -2
  4. data/{faq/faq.md → FAQ.md} +0 -43
  5. data/INSTALLATION.md +269 -0
  6. data/LICENSE +18 -22
  7. data/README.md +76 -128
  8. data/dependencies.yml +13 -0
  9. data/ext/sqlite3/aggregator.c +142 -146
  10. data/ext/sqlite3/aggregator.h +2 -4
  11. data/ext/sqlite3/backup.c +86 -64
  12. data/ext/sqlite3/backup.h +2 -2
  13. data/ext/sqlite3/database.c +543 -465
  14. data/ext/sqlite3/database.h +9 -4
  15. data/ext/sqlite3/exception.c +111 -92
  16. data/ext/sqlite3/exception.h +3 -1
  17. data/ext/sqlite3/extconf.rb +83 -51
  18. data/ext/sqlite3/sqlite3.c +160 -115
  19. data/ext/sqlite3/sqlite3_ruby.h +2 -2
  20. data/ext/sqlite3/statement.c +518 -293
  21. data/ext/sqlite3/statement.h +3 -3
  22. data/ext/sqlite3/timespec.h +20 -0
  23. data/lib/sqlite3/constants.rb +171 -47
  24. data/lib/sqlite3/database.rb +141 -181
  25. data/lib/sqlite3/errors.rb +26 -1
  26. data/lib/sqlite3/pragmas.rb +128 -138
  27. data/lib/sqlite3/resultset.rb +14 -105
  28. data/lib/sqlite3/statement.rb +58 -13
  29. data/lib/sqlite3/value.rb +17 -20
  30. data/lib/sqlite3/version.rb +1 -21
  31. data/lib/sqlite3.rb +6 -4
  32. data/ports/archives/sqlite-autoconf-3460000.tar.gz +0 -0
  33. metadata +19 -107
  34. data/API_CHANGES.md +0 -49
  35. data/ChangeLog.cvs +0 -88
  36. data/Gemfile +0 -3
  37. data/LICENSE-DEPENDENCIES +0 -20
  38. data/faq/faq.rb +0 -145
  39. data/faq/faq.yml +0 -426
  40. data/lib/sqlite3/translator.rb +0 -118
  41. data/ports/archives/sqlite-autoconf-3380500.tar.gz +0 -0
  42. data/test/helper.rb +0 -27
  43. data/test/test_backup.rb +0 -33
  44. data/test/test_collation.rb +0 -82
  45. data/test/test_database.rb +0 -545
  46. data/test/test_database_flags.rb +0 -95
  47. data/test/test_database_readonly.rb +0 -36
  48. data/test/test_database_readwrite.rb +0 -41
  49. data/test/test_deprecated.rb +0 -44
  50. data/test/test_encoding.rb +0 -155
  51. data/test/test_integration.rb +0 -507
  52. data/test/test_integration_aggregate.rb +0 -336
  53. data/test/test_integration_open_close.rb +0 -30
  54. data/test/test_integration_pending.rb +0 -115
  55. data/test/test_integration_resultset.rb +0 -142
  56. data/test/test_integration_statement.rb +0 -194
  57. data/test/test_result_set.rb +0 -37
  58. data/test/test_sqlite3.rb +0 -30
  59. data/test/test_statement.rb +0 -263
  60. data/test/test_statement_execute.rb +0 -35
@@ -4,14 +4,19 @@
4
4
  #include <sqlite3_ruby.h>
5
5
 
6
6
  struct _sqlite3Ruby {
7
- sqlite3 *db;
7
+ sqlite3 *db;
8
+ VALUE busy_handler;
9
+ int stmt_timeout;
10
+ struct timespec stmt_deadline;
8
11
  };
9
12
 
10
13
  typedef struct _sqlite3Ruby sqlite3Ruby;
11
- typedef sqlite3Ruby * sqlite3RubyPtr;
14
+ typedef sqlite3Ruby *sqlite3RubyPtr;
12
15
 
13
16
  void init_sqlite3_database();
14
- void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result);
15
- VALUE sqlite3val2rb(sqlite3_value * val);
17
+ void set_sqlite3_func_result(sqlite3_context *ctx, VALUE result);
18
+
19
+ sqlite3RubyPtr sqlite3_database_unwrap(VALUE database);
20
+ VALUE sqlite3val2rb(sqlite3_value *val);
16
21
 
17
22
  #endif
@@ -1,98 +1,117 @@
1
1
  #include <sqlite3_ruby.h>
2
2
 
3
- void rb_sqlite3_raise(sqlite3 * db, int status)
3
+ void
4
+ rb_sqlite3_raise(sqlite3 *db, int status)
4
5
  {
5
- VALUE klass = Qnil;
6
+ VALUE klass = Qnil;
6
7
 
7
- /* Consider only lower 8 bits, to work correctly when
8
- extended result codes are enabled. */
9
- switch(status & 0xff) {
10
- case SQLITE_OK:
11
- return;
12
- break;
13
- case SQLITE_ERROR:
14
- klass = rb_path2class("SQLite3::SQLException");
15
- break;
16
- case SQLITE_INTERNAL:
17
- klass = rb_path2class("SQLite3::InternalException");
18
- break;
19
- case SQLITE_PERM:
20
- klass = rb_path2class("SQLite3::PermissionException");
21
- break;
22
- case SQLITE_ABORT:
23
- klass = rb_path2class("SQLite3::AbortException");
24
- break;
25
- case SQLITE_BUSY:
26
- klass = rb_path2class("SQLite3::BusyException");
27
- break;
28
- case SQLITE_LOCKED:
29
- klass = rb_path2class("SQLite3::LockedException");
30
- break;
31
- case SQLITE_NOMEM:
32
- klass = rb_path2class("SQLite3::MemoryException");
33
- break;
34
- case SQLITE_READONLY:
35
- klass = rb_path2class("SQLite3::ReadOnlyException");
36
- break;
37
- case SQLITE_INTERRUPT:
38
- klass = rb_path2class("SQLite3::InterruptException");
39
- break;
40
- case SQLITE_IOERR:
41
- klass = rb_path2class("SQLite3::IOException");
42
- break;
43
- case SQLITE_CORRUPT:
44
- klass = rb_path2class("SQLite3::CorruptException");
45
- break;
46
- case SQLITE_NOTFOUND:
47
- klass = rb_path2class("SQLite3::NotFoundException");
48
- break;
49
- case SQLITE_FULL:
50
- klass = rb_path2class("SQLite3::FullException");
51
- break;
52
- case SQLITE_CANTOPEN:
53
- klass = rb_path2class("SQLite3::CantOpenException");
54
- break;
55
- case SQLITE_PROTOCOL:
56
- klass = rb_path2class("SQLite3::ProtocolException");
57
- break;
58
- case SQLITE_EMPTY:
59
- klass = rb_path2class("SQLite3::EmptyException");
60
- break;
61
- case SQLITE_SCHEMA:
62
- klass = rb_path2class("SQLite3::SchemaChangedException");
63
- break;
64
- case SQLITE_TOOBIG:
65
- klass = rb_path2class("SQLite3::TooBigException");
66
- break;
67
- case SQLITE_CONSTRAINT:
68
- klass = rb_path2class("SQLite3::ConstraintException");
69
- break;
70
- case SQLITE_MISMATCH:
71
- klass = rb_path2class("SQLite3::MismatchException");
72
- break;
73
- case SQLITE_MISUSE:
74
- klass = rb_path2class("SQLite3::MisuseException");
75
- break;
76
- case SQLITE_NOLFS:
77
- klass = rb_path2class("SQLite3::UnsupportedException");
78
- break;
79
- case SQLITE_AUTH:
80
- klass = rb_path2class("SQLite3::AuthorizationException");
81
- break;
82
- case SQLITE_FORMAT:
83
- klass = rb_path2class("SQLite3::FormatException");
84
- break;
85
- case SQLITE_RANGE:
86
- klass = rb_path2class("SQLite3::RangeException");
87
- break;
88
- case SQLITE_NOTADB:
89
- klass = rb_path2class("SQLite3::NotADatabaseException");
90
- break;
91
- default:
92
- klass = rb_eRuntimeError;
93
- }
8
+ /* Consider only lower 8 bits, to work correctly when
9
+ extended result codes are enabled. */
10
+ switch (status & 0xff) {
11
+ case SQLITE_OK:
12
+ return;
13
+ break;
14
+ case SQLITE_ERROR:
15
+ klass = rb_path2class("SQLite3::SQLException");
16
+ break;
17
+ case SQLITE_INTERNAL:
18
+ klass = rb_path2class("SQLite3::InternalException");
19
+ break;
20
+ case SQLITE_PERM:
21
+ klass = rb_path2class("SQLite3::PermissionException");
22
+ break;
23
+ case SQLITE_ABORT:
24
+ klass = rb_path2class("SQLite3::AbortException");
25
+ break;
26
+ case SQLITE_BUSY:
27
+ klass = rb_path2class("SQLite3::BusyException");
28
+ break;
29
+ case SQLITE_LOCKED:
30
+ klass = rb_path2class("SQLite3::LockedException");
31
+ break;
32
+ case SQLITE_NOMEM:
33
+ klass = rb_path2class("SQLite3::MemoryException");
34
+ break;
35
+ case SQLITE_READONLY:
36
+ klass = rb_path2class("SQLite3::ReadOnlyException");
37
+ break;
38
+ case SQLITE_INTERRUPT:
39
+ klass = rb_path2class("SQLite3::InterruptException");
40
+ break;
41
+ case SQLITE_IOERR:
42
+ klass = rb_path2class("SQLite3::IOException");
43
+ break;
44
+ case SQLITE_CORRUPT:
45
+ klass = rb_path2class("SQLite3::CorruptException");
46
+ break;
47
+ case SQLITE_NOTFOUND:
48
+ klass = rb_path2class("SQLite3::NotFoundException");
49
+ break;
50
+ case SQLITE_FULL:
51
+ klass = rb_path2class("SQLite3::FullException");
52
+ break;
53
+ case SQLITE_CANTOPEN:
54
+ klass = rb_path2class("SQLite3::CantOpenException");
55
+ break;
56
+ case SQLITE_PROTOCOL:
57
+ klass = rb_path2class("SQLite3::ProtocolException");
58
+ break;
59
+ case SQLITE_EMPTY:
60
+ klass = rb_path2class("SQLite3::EmptyException");
61
+ break;
62
+ case SQLITE_SCHEMA:
63
+ klass = rb_path2class("SQLite3::SchemaChangedException");
64
+ break;
65
+ case SQLITE_TOOBIG:
66
+ klass = rb_path2class("SQLite3::TooBigException");
67
+ break;
68
+ case SQLITE_CONSTRAINT:
69
+ klass = rb_path2class("SQLite3::ConstraintException");
70
+ break;
71
+ case SQLITE_MISMATCH:
72
+ klass = rb_path2class("SQLite3::MismatchException");
73
+ break;
74
+ case SQLITE_MISUSE:
75
+ klass = rb_path2class("SQLite3::MisuseException");
76
+ break;
77
+ case SQLITE_NOLFS:
78
+ klass = rb_path2class("SQLite3::UnsupportedException");
79
+ break;
80
+ case SQLITE_AUTH:
81
+ klass = rb_path2class("SQLite3::AuthorizationException");
82
+ break;
83
+ case SQLITE_FORMAT:
84
+ klass = rb_path2class("SQLite3::FormatException");
85
+ break;
86
+ case SQLITE_RANGE:
87
+ klass = rb_path2class("SQLite3::RangeException");
88
+ break;
89
+ case SQLITE_NOTADB:
90
+ klass = rb_path2class("SQLite3::NotADatabaseException");
91
+ break;
92
+ default:
93
+ klass = rb_path2class("SQLite3::Exception");
94
+ }
94
95
 
95
- klass = rb_exc_new2(klass, sqlite3_errmsg(db));
96
- rb_iv_set(klass, "@code", INT2FIX(status));
97
- rb_exc_raise(klass);
96
+ klass = rb_exc_new2(klass, sqlite3_errmsg(db));
97
+ rb_iv_set(klass, "@code", INT2FIX(status));
98
+ rb_exc_raise(klass);
99
+ }
100
+
101
+ /*
102
+ * accepts a sqlite3 error message as the final argument, which will be `sqlite3_free`d
103
+ */
104
+ void
105
+ rb_sqlite3_raise_msg(sqlite3 *db, int status, const char *msg)
106
+ {
107
+ VALUE exception;
108
+
109
+ if (status == SQLITE_OK) {
110
+ return;
111
+ }
112
+
113
+ exception = rb_exc_new2(rb_path2class("SQLite3::Exception"), msg);
114
+ sqlite3_free((void *)msg);
115
+ rb_iv_set(exception, "@code", INT2FIX(status));
116
+ rb_exc_raise(exception);
98
117
  }
@@ -2,7 +2,9 @@
2
2
  #define SQLITE3_EXCEPTION_RUBY
3
3
 
4
4
  #define CHECK(_db, _status) rb_sqlite3_raise(_db, _status);
5
+ #define CHECK_MSG(_db, _status, _msg) rb_sqlite3_raise_msg(_db, _status, _msg);
5
6
 
6
- void rb_sqlite3_raise(sqlite3 * db, int status);
7
+ void rb_sqlite3_raise(sqlite3 *db, int status);
8
+ void rb_sqlite3_raise_msg(sqlite3 *db, int status, const char *msg);
7
9
 
8
10
  #endif
@@ -1,5 +1,5 @@
1
1
  require "mkmf"
2
- require "mini_portile2"
2
+ require "yaml"
3
3
 
4
4
  module Sqlite3
5
5
  module ExtConf
@@ -19,7 +19,7 @@ module Sqlite3
19
19
 
20
20
  configure_extension
21
21
 
22
- create_makefile('sqlite3/sqlite3_native')
22
+ create_makefile("sqlite3/sqlite3_native")
23
23
  end
24
24
 
25
25
  def configure_cross_compiler
@@ -49,15 +49,22 @@ module Sqlite3
49
49
 
50
50
  def configure_packaged_libraries
51
51
  minimal_recipe.tap do |recipe|
52
- recipe.configure_options += ["--enable-shared=no", "--enable-static=yes"]
52
+ recipe.configure_options += [
53
+ "--enable-shared=no",
54
+ "--enable-static=yes",
55
+ "--enable-fts5"
56
+ ]
53
57
  ENV.to_h.tap do |env|
54
- additional_cflags = [
58
+ user_cflags = with_config("sqlite-cflags")
59
+ more_cflags = [
55
60
  "-fPIC", # needed for linking the static library into a shared library
56
61
  "-O2", # see https://github.com/sparklemotion/sqlite3-ruby/issues/335 for some benchmarks
62
+ "-fvisibility=hidden", # see https://github.com/rake-compiler/rake-compiler-dock/issues/87
63
+ "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1"
57
64
  ]
58
- env["CFLAGS"] = [env["CFLAGS"], additional_cflags].flatten.join(" ")
59
- recipe.configure_options += env.select { |k,v| ENV_ALLOWLIST.include?(k) }
60
- .map { |key, value| "#{key}=#{value.strip}" }
65
+ env["CFLAGS"] = [user_cflags, env["CFLAGS"], more_cflags].flatten.join(" ")
66
+ recipe.configure_options += env.select { |k, v| ENV_ALLOWLIST.include?(k) }
67
+ .map { |key, value| "#{key}=#{value.strip}" }
61
68
  end
62
69
 
63
70
  unless File.exist?(File.join(recipe.target, recipe.host, recipe.name, recipe.version))
@@ -65,22 +72,32 @@ module Sqlite3
65
72
  end
66
73
  recipe.activate
67
74
 
68
- ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t" # on macos, pkg-config will not return --cflags without this
69
- pcfile = File.join(recipe.path, "lib", "pkgconfig", "sqlite3.pc")
70
- if pkg_config(pcfile)
71
- # see https://bugs.ruby-lang.org/issues/18490
72
- libs = xpopen(["pkg-config", "--libs", "--static", pcfile], err: [:child, :out], &:read)
73
- libs.split.each { |lib| append_ldflags(lib) } if $?.success?
74
- else
75
- abort("\nCould not configure the build properly. Please install either the `pkg-config` utility or the `pkg-config` rubygem.\n\n")
75
+ # on macos, pkg-config will not return --cflags without this
76
+ ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t"
77
+
78
+ # only needed for Ruby 3.1.3, see https://bugs.ruby-lang.org/issues/19233
79
+ RbConfig::CONFIG["PKG_CONFIG"] = config_string("PKG_CONFIG") || "pkg-config"
80
+
81
+ lib_path = File.join(recipe.path, "lib")
82
+ pcfile = File.join(lib_path, "pkgconfig", "sqlite3.pc")
83
+ abort_pkg_config("pkg_config") unless pkg_config(pcfile)
84
+
85
+ # see https://bugs.ruby-lang.org/issues/18490
86
+ ldflags = xpopen(["pkg-config", "--libs", "--static", pcfile], err: [:child, :out], &:read)
87
+ abort_pkg_config("xpopen") unless $?.success?
88
+ ldflags = ldflags.split
89
+
90
+ # see https://github.com/flavorjones/mini_portile/issues/118
91
+ "-L#{lib_path}".tap do |lib_path_flag|
92
+ ldflags.prepend(lib_path_flag) unless ldflags.include?(lib_path_flag)
76
93
  end
94
+
95
+ ldflags.each { |ldflag| append_ldflags(ldflag) }
77
96
  end
78
97
  end
79
98
 
80
99
  def configure_extension
81
- if Gem::Requirement.new("< 2.7").satisfied_by?(Gem::Version.new(RUBY_VERSION))
82
- append_cppflags("-DTAINTING_SUPPORT")
83
- end
100
+ append_cflags("-fvisibility=hidden") # see https://github.com/rake-compiler/rake-compiler-dock/issues/87
84
101
 
85
102
  if find_header("sqlite3.h")
86
103
  # noop
@@ -92,33 +109,43 @@ module Sqlite3
92
109
 
93
110
  abort_could_not_find(libname) unless find_library(libname, "sqlite3_libversion_number", "sqlite3.h")
94
111
 
112
+ # Truffle Ruby doesn't support this yet:
113
+ # https://github.com/oracle/truffleruby/issues/3408
114
+ have_func("rb_enc_interned_str_cstr")
115
+
95
116
  # Functions defined in 1.9 but not 1.8
96
- have_func('rb_proc_arity')
117
+ have_func("rb_proc_arity")
97
118
 
98
119
  # Functions defined in 2.1 but not 2.0
99
- have_func('rb_integer_pack')
120
+ have_func("rb_integer_pack")
100
121
 
101
122
  # These functions may not be defined
102
- have_func('sqlite3_initialize')
103
- have_func('sqlite3_backup_init')
104
- have_func('sqlite3_column_database_name')
105
- have_func('sqlite3_enable_load_extension')
106
- have_func('sqlite3_load_extension')
123
+ have_func("sqlite3_initialize")
124
+ have_func("sqlite3_backup_init")
125
+ have_func("sqlite3_column_database_name")
126
+ have_func("sqlite3_enable_load_extension")
127
+ have_func("sqlite3_load_extension")
107
128
 
108
- unless have_func('sqlite3_open_v2') # https://www.sqlite.org/releaselog/3_5_0.html
129
+ unless have_func("sqlite3_open_v2") # https://www.sqlite.org/releaselog/3_5_0.html
109
130
  abort("\nPlease use a version of SQLite3 >= 3.5.0\n\n")
110
131
  end
111
132
 
112
- have_func('sqlite3_prepare_v2')
113
- have_type('sqlite3_int64', 'sqlite3.h')
114
- have_type('sqlite3_uint64', 'sqlite3.h')
133
+ have_func("sqlite3_prepare_v2")
134
+ have_type("sqlite3_int64", "sqlite3.h")
135
+ have_type("sqlite3_uint64", "sqlite3.h")
115
136
  end
116
137
 
117
138
  def minimal_recipe
139
+ require "mini_portile2"
140
+
118
141
  MiniPortile.new(libname, sqlite3_config[:version]).tap do |recipe|
119
- recipe.files = sqlite3_config[:files]
120
- recipe.target = File.join(package_root_dir, "ports")
121
- recipe.patch_files = Dir[File.join(package_root_dir, "patches", "*.patch")].sort
142
+ if sqlite_source_dir
143
+ recipe.source_directory = sqlite_source_dir
144
+ else
145
+ recipe.files = sqlite3_config[:files]
146
+ recipe.target = File.join(package_root_dir, "ports")
147
+ recipe.patch_files = Dir[File.join(package_root_dir, "patches", "*.patch")].sort
148
+ end
122
149
  end
123
150
  end
124
151
 
@@ -131,37 +158,33 @@ module Sqlite3
131
158
  end
132
159
 
133
160
  def mini_portile_config
134
- {
135
- sqlite3: {
136
- # checksum verified by first checking the published sha3(256) checksum against https://sqlite.org/download.html:
137
- #
138
- # $ sha3sum -a 256 ports/archives/sqlite-autoconf-3390300.tar.gz
139
- # dfa055c70724cd63f0b7da6e9f53530d8da51fe021e3f864d58c7c847d590e1d ports/archives/sqlite-autoconf-3390300.tar.gz
140
- #
141
- # $ sha256sum ports/archives/sqlite-autoconf-3390300.tar.gz
142
- # 7868fb3082be3f2cf4491c6fba6de2bddcbc293a35fefb0624ee3c13f01422b9 ports/archives/sqlite-autoconf-3390300.tar.gz
143
- #
144
- version: "3.39.3",
145
- files: [{
146
- url: "https://www.sqlite.org/2022/sqlite-autoconf-3390300.tar.gz",
147
- sha256: "7868fb3082be3f2cf4491c6fba6de2bddcbc293a35fefb0624ee3c13f01422b9",
148
- }],
149
- }
150
- }
161
+ YAML.load_file(File.join(package_root_dir, "dependencies.yml"), symbolize_names: true)
151
162
  end
152
163
 
153
164
  def abort_could_not_find(missing)
154
165
  abort("\nCould not find #{missing}.\nPlease visit https://github.com/sparklemotion/sqlite3-ruby for installation instructions.\n\n")
155
166
  end
156
167
 
168
+ def abort_pkg_config(id)
169
+ abort("\nCould not configure the build properly (#{id}). Please install either the `pkg-config` utility or the `pkg-config` rubygem.\n\n")
170
+ end
171
+
157
172
  def cross_build?
158
173
  enable_config("cross-build")
159
174
  end
160
175
 
176
+ def sqlite_source_dir
177
+ arg_config("--with-sqlite-source-dir")
178
+ end
179
+
161
180
  def download
162
181
  minimal_recipe.download
163
182
  end
164
183
 
184
+ def darwin?
185
+ RbConfig::CONFIG["target_os"].include?("darwin")
186
+ end
187
+
165
188
  def print_help
166
189
  print(<<~TEXT)
167
190
  USAGE: ruby #{$PROGRAM_NAME} [options]
@@ -179,6 +202,9 @@ module Sqlite3
179
202
  Use libsqlcipher instead of libsqlite3.
180
203
  (Implies `--enable-system-libraries`.)
181
204
 
205
+ --with-sqlite-source-dir=DIRECTORY
206
+ (dev only) Build sqlite from the source code in DIRECTORY
207
+
182
208
  --help
183
209
  Display this message.
184
210
 
@@ -213,17 +239,23 @@ module Sqlite3
213
239
 
214
240
  Flags only used when building and using the packaged libraries:
215
241
 
242
+ --with-sqlite-cflags=CFLAGS
243
+ Explicitly pass compiler flags to the sqlite library build. These flags will
244
+ appear on the commandline before any flags set in the CFLAGS environment
245
+ variable. This is useful for setting compilation options in your project's
246
+ bundler config. See INSTALLATION.md for more information.
247
+
216
248
  --enable-cross-build
217
249
  Enable cross-build mode. (You probably do not want to set this manually.)
218
250
 
219
251
 
220
- Environment variables used for compiling the C extension:
252
+ Environment variables used for compiling the gem's C extension:
221
253
 
222
254
  CC
223
255
  Use this path to invoke the compiler instead of `RbConfig::CONFIG['CC']`
224
256
 
225
257
 
226
- Environment variables passed through to the compilation of packaged libraries:
258
+ Environment variables passed through to the compilation of sqlite:
227
259
 
228
260
  CC
229
261
  CPPFLAGS