canonical/libco - "Undefined symbols for architecture" MacOS 上的编译和链接问题

Compilation and linking issues on MacOS for canonical/libco - "Undefined symbols for architecture"

我使用的是 MacOS Catalina 10.15.3。我正在尝试构建 Caonical 的 dqlite as I want to try the experimental features of k3s which uses it as distributed database instead of 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

当我尝试构建一个简单的测试文件时出现问题(请忽略此文件中的错误,我尝试将 this one 改编为独立测试):

#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 或库路径解析问题,但我似乎无法弄清楚。
我错过了什么?

谢谢。

您需要告诉 clang 包含文件在哪里、库在哪个目录中以及您要使用哪些库:

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