Можно ли создавать расширения sqlite на Apple Silicon с помощью clang?

Я пытаюсь создать расширение sqlite процентиля на ноутбуке M1, используя инструкции на странице:

gcc -g -fPIC -shared percentile.c -o percentile.so

Однако это приводит к следующим ошибкам из clang:

$ gcc -g -fPIC -shared percentile.c -o percentile.so
Undefined symbols for architecture arm64:
  "_sqlite3_aggregate_context", referenced from:
      _percentStep in percentile-a11598.o
      _percentFinal in percentile-a11598.o
  "_sqlite3_create_function", referenced from:
      _sqlite3_percentile_init in percentile-a11598.o
      _sqlite3_percentile_init in percentile-a11598.o
      _sqlite3_percentile_init in percentile-a11598.o
  "_sqlite3_free", referenced from:
      _percentStep in percentile-a11598.o
      _percentFinal in percentile-a11598.o
  "_sqlite3_realloc64", referenced from:
      _percentStep in percentile-a11598.o
  "_sqlite3_result_double", referenced from:
      _percentFinal in percentile-a11598.o
  "_sqlite3_result_error", referenced from:
      _percentStep in percentile-a11598.o
      _percentStep in percentile-a11598.o
      _percentStep in percentile-a11598.o
      _percentStep in percentile-a11598.o
      _percentStep in percentile-a11598.o
  "_sqlite3_result_error_nomem", referenced from:
      _percentStep in percentile-a11598.o
  "_sqlite3_user_data", referenced from:
      _percentStep in percentile-a11598.o
  "_sqlite3_value_double", referenced from:
      _percentStep in percentile-a11598.o
      _percentStep in percentile-a11598.o
      _percentStep in percentile-a11598.o
  "_sqlite3_value_numeric_type", referenced from:
      _percentStep in percentile-a11598.o
      _percentStep in percentile-a11598.o
  "_sqlite3_value_type", referenced from:
      _percentStep in percentile-a11598.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Можно ли создавать расширения sqlite с помощью clang, или мне нужен настоящий GCC, чтобы это работало?

🤔 А знаете ли вы, что...
C предоставляет множество возможностей для манипуляции памятью, что может быть как преимуществом, так и недостатком.


1
57
1

Ответ:

Решено

После долгих экспериментов у меня получилось кое-что, что работает. Нужная вам команда больше похожа на следующую, поскольку в macOS библиотеки общих объектов заканчиваются на .dylib:

gcc -g -fPIC -dynamiclib -undefined suppress percentile.c -o percentile.dylib

хотя оно выдает предупреждение ld: warning: -undefined suppress is deprecated, с которым может помочь кто-то умнее меня (их много).

Однако при попытке загрузить его произойдет ошибка, если вы используете предоставленную Apple команду sqlite3 в /usr/bin/sqlite3. Вы можете узнать, какой из них вы используете, запустив:

type sqlite3
sqlite3 is /usr/bin/sqlite3

При попытке загрузить его вы получаете:

sqlite> .load percentile
Error: unknown command or invalid arguments:  "load". Enter ".help" for help

Если вы затем проверите, как Apple компилирует sqlite3 с помощью:

sqlite3 :memory: 'select * from pragma_compile_options()'

Выход

ATOMIC_INTRINSICS=1
BUG_COMPATIBLE_20160819
CCCRYPT256
COMPILER=clang-15.0.0
DEFAULT_AUTOVACUUM
DEFAULT_CACHE_SIZE=2000
DEFAULT_CKPTFULLFSYNC
DEFAULT_FILE_FORMAT=4
DEFAULT_JOURNAL_SIZE_LIMIT=32768
DEFAULT_LOOKASIDE=1200,102
...
...
MAX_TRIGGER_DEPTH=1000
MAX_VARIABLE_NUMBER=500000
MAX_VDBE_OP=250000000
MAX_WORKER_THREADS=8
MUTEX_UNFAIR
OMIT_AUTORESET
OMIT_LOAD_EXTENSION                  <--- OOPS, ".load" not built in
STMTJRNL_SPILL=131072
SYSTEM_MALLOC
TEMP_STORE=1
THREADSAFE=2
USE_URI

Вы можете видеть, что Apple не разрешает команду .load. Итак, вам нужно либо собрать весь sqlite3 самостоятельно (разумеется, без OMIT_LOAD_EXTENSION), либо использовать доморощенный вариант для установки их исполняемого файла:

brew install sqlite

Затем вы можете запустить:

/opt/homebrew/Cellar/sqlite/3.46.0/bin/sqlite3 :memory: 'select * from pragma_compile_options()'

и вы увидите, что команда .load поддерживается. Теперь вы можете сделать:

/opt/homebrew/Cellar/sqlite/3.46.0/bin/sqlite3
sqlite> .load percentile
sqlite> 

Обратите внимание, что я использовал /opt/homebrew/Cellar/sqlite/3.46.0/bin/sqlite3, тогда как вам следует использовать "$(brew --prefix)/Cellar/sqlite/3.46.0/bin/sqlite3" более правильно, потому что это будет работать на компьютерах Intel Mac (которые используют /usr/local/Cellar), а также Apple Silicon (которые используют /opt/homebrew/Cellar).