Неопределенная ссылка на мою собственную функцию в проекте Meson во время компоновки

#c #meson-build

#c #meson-build

Вопрос:

У меня есть проект Meson C со следующей компоновкой:

 ├── include
│   ├── cxxopts.hpp
│   ├── json.hpp
│   ├── loguru
│   └── redis-cpp
├── meson.build
└── src
    ├── frame_utils
    │   ├── frame_utils.cpp
    │   ├── frame_utils.h
    │   └── meson.build
    ├── meson.build
    ├── source.cpp
 

Основной meson.build файл включает в себя следующее:

 project(
  'test',
  'cpp',
  version : '0.1',
  default_options :
    ['warning_level=3', 'cpp_std=c  17']
)

compiler = meson.get_compiler('cpp')
all_deps = [
  dependency('threads'),
  compiler.find_library('dl', required : false),
  # additional deps filled by subdirectories
]

all_includes = [
  include_directories('include/redis-cpp'),
  include_directories('include/loguru'),
  include_directories('include')
]

# filled by subdirectories
source_files = []

subdir('src')
 

Тот, который находится внутри src , имеет следующий код:

 subdir('frame_utils')

exe = executable(
  'source',
  'source.cpp',
  install : false,
  include_directories : all_includes,
  dependencies : all_deps,
  link_with: frame_utils_lib
)
 

И тот, который в frame_utils :

 all_includes  = include_directories('.')

frame_utils_lib = static_library(
  'frame_utils',
  'frame_utils.cpp',
  install : false
)
 

Библиотека очень проста, состоит из пространства имен и одной функции:

 #ifndef FRAME_UTILS_H
#define FRAME_UTILS_H

#include <cstdlib>

namespace frame_utils {
double timecode_to_ms(int64_t timestamp);
}

#endif
 

Теперь в моем source.cpp файле я вызываю функцию из frame_utils , например, так:

 #include "frame_utils.h"

// ...

frame_utils::timecode_to_ms(video_frame.timestamp)
 

Здесь video_frame.timestamp int64_t .

Когда я создаю проект, я получаю следующую ошибку из ld :

 FAILED: src/source
c    -o src/source src/source.p/source.cpp.o -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group src/frame_utils/libframe_utils.a -pthread -ldl -Wl,--end-group
/usr/bin/ld: src/source.p/source.cpp.o: in function `...':
/builddir/../src/source.cpp:111: undefined reference to `frame_utils::timecode_to_ms(long)'
/usr/bin/ld: /builddir/../src/source.cpp:112: undefined reference to `frame_utils::timecode_to_ms(long)'
collect2: error: ld returned 1 exit status
 

Код Visual Studio способен правильно разрешать пространство имен и имя / подпись функции. Чего мне не хватает?

Библиотека определенно экспортирует эту функцию:

 $ nm builddir/src/frame_utils/libframe_utils.a

frame_utils.cpp.o:
0000000000000000 T _Z14timecode_to_msl
 

Кроме того, когда я копирую ту же функцию с той же подписью (только без пространства имен) в source.cpp файл, она работает правильно.

Ответ №1:

Ошибка была связана с определением самой функции в .cpp файле. Это должно быть настроено следующим образом:

 #include "frame_utils.h"

namespace frame_utils {
double timecode_to_ms(int64_t timestamp) {
  return (double)timestamp / 10000.0;
}
}
 

Раньше это было так:

 #include "frame_utils.h"

using namespace frame_utils;

double timecode_to_ms(int64_t timestamp) {
  return (double)timestamp / 10000.0;
}
 

По какой-то причине VS Code смог разрешить эту функцию, но компоновщик — нет.