【问题标题】:C project build with meson: Correct way to handle 3rd party local libraries使用介子构建 C 项目:处理 3rd 方本地库的正确方法
【发布时间】:2020-03-28 19:24:00
【问题描述】:

我想构建一个使用Criterion 测试库的项目,我正在使用介子来构建它。我能够构建自己的代码,一个仅依赖于标准 c 库的静态库。单元测试依赖于#include <criterion/criterion.h>。如果我尝试下载二进制存档并将其包含在 meson.build 文件中,我将无法成功构建项目。我相信我没有正确地配置介子。我是介子新手,所以我不确定我错了什么。

meson.build

project('is_substring', 'c')

static_library(
    'is_substring',
    'is_substring.h',
)

executable(
    'test_is_substring',
    'is_substring.test.c',
    include_directories: include_directories(
        'libs/criterion-v2.3.3',
    ),
    #dependencies: [
    #    dependency('criterion')
    #]
)

项目结构是,


  ▸ builddir/
  ▸ libs/criterion-v2.3.3/
    is_substring.h
    is_substring.test.c
    meson.build

并且 Criterion 二进制存档 tar.bz2 已提取到 ./libs

  ▾ libs/criterion-v2.3.3/
    ▾ include/criterion/
      ▸ internal/
        abort.h
        alloc.h
        assert.h
        criterion.h
        event.h
        hooks.h
        logging.h
        options.h
        output.h
        parameterized.h
        redirect.h
        stats.h
        theories.h
        types.h
    ▾ lib/
        libcriterion.so
        libcriterion.so.3
        libcriterion.so.3.1.0
    ▾ share/pkgconfig/
        criterion.pc

is_substring.test.c,

#include "criterion/criterion.h"
#include <stdbool.h>
#include <stdio.h>

#include "is_substring.h"


Test(is_substring, is_substring)
{
    cr_assert(is_substring("aaa", "a") == true);
}

is_substring.h,

#include "stdbool.h"

bool is_substring(const char *fullstr, const char *substr)
{
    return true;
}

我尝试构建时的错误是,

francium@4ab5198f934f:/mnt/c/brute-force/builddir$ ninja
[1/2] Compiling C object 'test_is_substring@exe/is_substring.test.c.o'.
FAILED: test_is_substring@exe/is_substring.test.c.o
cc -Itest_is_substring@exe -I. -I.. -I../libs/criterion-v2.3.3 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -MD -MQ 'test_is_substring@exe/is_substring.test.c.o' -MF 'test_is_substring@exe/is_substring.test.c.o.d' -o 'test_is_substring@exe/is_substring.test.c.o' -c ../is_substring.test.c
../is_substring.test.c:1:10: fatal error: criterion/criterion.h: No such file or directory
 #include <criterion/criterion.h>
          ^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
ninja: build stopped: subcommand failed.
francium@4ab5198f934f:/mnt/c/brute-force/builddir$

正如@jonathan-leffler 在 cmets 中指出的那样,这个 gcc 命令可以正常工作、编译和链接,

gcc -o is_substring.test is_substring.test.c -I libs/criterion-v2.3.3/include/ -Llibs/criterion-v2.3.3/lib -lcriterion

【问题讨论】:

  • include_directories: include_directories( 'libs/criterion-v2.3.3', ),改成include_directories: include_directories( 'libs/criterion-v2.3.3/include', ),会更好吗?想法是包含目录在libs/criterion-v2.3.3下如此命名。
  • @JonathanLeffler 是的,然后它设法编译,但在链接期间它无法找到 .so 文件。我不知道如何告诉介子在哪里寻找可链接的库文件。我想如果我只是将它指向整个目录而不仅仅是 include/ 它会按照惯例解决。
  • 根据我所见,您应该使用gcc … -Llib/criterion-v2.3.3/lib -lcriterion …。库参数应该出现在最后一个目标文件之后。如果您自己的库调用 Criterion 库,它应该在命令行上位于 Criterion 库之前。如果它们是独立的,则顺序不应该是关键的。
  • 名义上,您建议的带有-lcriterion ./libs/…/libcriterion.so 的命令行会链接同一个库两次。
  • 订购时:-L 选项需要继续 -l 选项,具体取决于该位置。在任何库之前列出所有对象(或源)文件通常是最明智的。有时有理由采取不同的做法,但并不经常这样做。然后可以使用静态或共享库。有时事情以不同的顺序工作;有时他们不会。如果要成功使用静态库,则确实需要在库中包含 DAG(库之间没有循环依赖关系)。共享库可以隐藏排序问题。可以有编译器/链接器选项来提供帮助。

标签: c meson-build


【解决方案1】:

设法让它编译,但由于 Criterion 库是一个共享库并且它不是全局安装的,如果你只是尝试运行编译的测试可执行文件,它就不起作用。

但是让它编译的修复方法是添加一个,

executable(
    ...
    objects: [
        'libs/criterion-v2.3.3/lib/libcriterion.so',
    ]

请注意,include_directories 路径也应该是 'libs/criterion-v2.3.3/include/',并在末尾加上 include/

完整的meson.build

project('is_substring', 'c')

static_library(
    'is_substring',
    'is_substring.h',
)

include_criterion = include_directories(
    'libs/criterion-v2.3.3/include/',
)

executable(
    'test_is_substring',
    'is_substring.test.c',
    include_directories: [
        include_criterion,
    ],
    objects: [
        'libs/criterion-v2.3.3/lib/libcriterion.so',
    ]
)

但运行输出可执行文件会在运行时出现以下错误,

./test_is_substring: error while loading shared libraries: libcriterion.so.3: cannot open shared object file: No such file or directory

正如 Jonathan 所建议的,已修复此问题,

如果要将 Criterion 库安装到这些位置之一,则可能需要指定 -R/opt/criterion-v2.3.3/lib 或 -R/usr/local/lib。或者这可能在 Solaris 中被记错了,与 Linux 无关。无论如何,系统可能会在 /usr/local/lib 中查找。还有 LD_LIBRARY_PATH;您可以将 /home/you/project/libs/criterion-v2.3.3/lib (或其他)添加到您的 LD_LIBRARY_PATH 环境变量中,这应该允许在正式安装之前将其拾取

感谢@jonathan-leffler 的帮助和洞察力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    相关资源
    最近更新 更多