Проблемы компиляции и компоновки в MacOS для canonical / libco - «Неопределенные символы для архитектуры» - PullRequest
0 голосов
/ 09 февраля 2020

Я на MacOS Catalina 10.15.3. Я пытаюсь построить dqlite от Caonical, так как хочу попробовать экспериментальные функции k3s, который использует его как распределенную базу данных вместо etcd или другие.
Ошибка, с которой я сталкиваюсь, связана с одной из зависимостей: libco.

Я создал библиотеку с помощью следующих команд:

clang libco.c -g -O2 -Wall -fPIC -c -DLIBCO_MP
clang libco.o -dynamiclib -Wl,-install_name,libco.dylib -o libco.dylib

и я переместил эти файлы в /usr/local/lib/libco.dylib и /usr/local/include/libco.h соответственно.

Проблема возникает, когда я пытаюсь создать простой тестовый файл (пожалуйста, игнорируйте ошибки в этом файле, я пытался адаптировать этот в качестве автономного теста):

#include <libco.h>
#include <stdlib.h>
#include <assert.h>

/* Execution context of a test coroutine, passed using the global ctx
* variable. */
struct ctx
{
  cothread_t main; /* Reference to the main coroutine */
  int v1;
  int v2;
};

static struct ctx *ctx; /* Argument for test coroutines */

struct fixture
{
  cothread_t main;  /* Main coroutine */
  cothread_t coro1; /* First coroutine */
  cothread_t coro2; /* Second coroutine */
  struct ctx ctx1;  /* Context for first coroutine */
  struct ctx ctx2;  /* Context for second coroutine */
};

static void coro()
{
  struct ctx *c = ctx;
  c->v1 = 1;
  co_switch(c->main);
  c->v2 = 2;
  co_switch(c->main);
}

int main()
{
  struct fixture *f = malloc(sizeof *f);
  f->main = co_active();
  f->coro1 = co_create(1024 * 1024, coro);
  f->coro2 = co_create(1024 * 1024, coro);
  f->ctx1.main = f->main;
  f->ctx2.main = f->main;

  /* Start executing coro1 */
  ctx = &f->ctx1;
  co_switch(f->coro1);

  /* The v1 field of the context has been initialized, but v2 has not. */
  assert(f->ctx1.v1 == 1);
  assert(f->ctx1.v2 == 0);

  /* Start executing coro2 */
  ctx = &f->ctx2;
  co_switch(f->coro2);

  /* The v1 field of the second context has been initialized, but v2 has
   * not. */
  assert(f->ctx2.v1 == 1);
  assert(f->ctx2.v2 == 0);

  /* The fields of the first context are still the same. */
  assert(f->ctx1.v1 == 1);
  assert(f->ctx1.v2 == 0);

  /* Resume execution of coro2 */
  co_switch(f->coro2);

  /* The v2 field of the second context has been initialized too, but the
   * one of the first context still hasn't. */
  assert(f->ctx2.v1 == 1);
  assert(f->ctx2.v2 == 2);
  assert(f->ctx1.v1 == 1);
  assert(f->ctx1.v2 == 0);

  /* Resume execution of coro1 */
  co_switch(f->coro1);

  /* The v2 field of the first context has been initialized too now. */
  assert(f->ctx1.v1 == 1);
  assert(f->ctx1.v2 == 2);

  co_delete(f->coro1);
  co_delete(f->coro2);
  free(f);
  return 0;
}

Попытка компилировать с использованием clang test.c -o test приводит к следующему:

Undefined symbols for architecture x86_64:
  "_co_active", referenced from:
      _main in test-b98908.o
  "_co_create", referenced from:
      _main in test-b98908.o
  "_co_delete", referenced from:
      _main in test-b98908.o
  "_co_switch", referenced from:
      _main in test-b98908.o
      _coro in test-b98908.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Однако при дальнейшей проверке Я обнаружил, что эти символы, похоже, определены в библиотеке libco.dylib:

$ lipo -info /usr/local/lib/libco.dylib
Non-fat file: /usr/local/lib/libco.dylib is architecture: x86_64

$ nm /usr/local/lib/libco.dylib
                 U ___assert_rtn
0000000000005058 d __dyld_private
                 U __tlv_bootstrap
0000000000001d60 T _co_active
0000000000005040 s _co_active_buffer
0000000000005070 s _co_active_buffer$tlv$init
0000000000005028 s _co_active_handle
0000000000005060 s _co_active_handle$tlv$init
0000000000001e60 T _co_create
0000000000001f20 T _co_delete
0000000000001da0 T _co_derive
0000000000001f50 T _co_serializable
0000000000005270 b _co_swap
0000000000002000 s _co_swap_function
0000000000001f30 T _co_switch
0000000000001f60 t _crash
0000000000001f70 t _crash.cold.1
                 U _free
                 U _malloc
                 U _mprotect
                 U _sysconf
                 U dyld_stub_binder

Я думаю, единственная оставшаяся опция - это то, что компилятор не находит библиотеку, поэтому проблема может быть в name или проблема разрешения пути к библиотеке, но я не могу понять это.
Что я ssing?

Спасибо.

1 Ответ

1 голос
/ 09 февраля 2020

Вы должны указать clang, где находятся включаемые файлы, в каком каталоге находятся библиотеки и какие библиотеки вы хотите использовать:

clang program.c -o program -I/usr/local/include -L/usr/local/lib -lco
...