LINUX.ORG.RU

Ошибка при линковке shared библиотеки при использовании cmake

 , ,


0

3

Имею проект с такой структурой

* test_dpi
  * dpi
    * include
      * typedefs.h
      * streams.h
    * src
      * typedefs.cpp
      * streams.cpp
    * CMakeLists.txt
  * main.cpp
  * CMakeLists.txt

typedefs.h

#pragma once

#include <iostream>
#include <vector>

#define DECLARE_SERIALIZATION template<typename Ar> void serialize(Ar& ar, const unsigned version);

namespace DPI
{
    enum class Direction : int {
        Forward = 1,
        Reverse
    };

    struct Flow {
        uint64_t id{};

        DECLARE_SERIALIZATION
    };

    struct Packet {
        uint64_t flow_id{};

        DECLARE_SERIALIZATION
    };

    struct Dump {
        std::vector<Packet> packets;
        std::vector<Flow> flows;

        DECLARE_SERIALIZATION
    };
}

streams.h

#pragma once

#include "typedefs.h"

#include <boost/filesystem.hpp>
#include <boost/archive/binary_wiarchive.hpp>
#include <boost/archive/binary_woarchive.hpp>

namespace DPI
{
    bool load(const std::wstring& path, Dump& dump);
    bool dump(const std::wstring& path, const Dump& dump);
}

main.cpp

#include "dpi/streams.h"

int main() {
    std::cout << "Hello, World!" << std::endl;

    DPI::Dump dump;
    DPI::dump(L"this.bin", dump);

    return 0;
}

dpi/CMakeLists.txt

cmake_minimum_required(VERSION 3.12)
project(dpi)

add_library(dpi SHARED
        include/dpi/typedefs.h include/dpi/streams.h
        src/typedefs.cpp src/streams.cpp
        )

target_include_directories(dpi PRIVATE ./include/dpi)

CMakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(test_dpi)

set(CMAKE_CXX_STANDARD 17)
find_package(Boost REQUIRED)

add_subdirectory(dpi)
include_directories(${dpi_SOURCE_DIR}/include)

add_executable(test_dpi main.cpp)
link_libraries(test_dpi boost_system boost_serialization boost_wserialization dpi)

Сам подпроект компилируется нормально, но при попытке собрать test_dpi в терминале появляются такие ошибки

====================[ Build | test_dpi | Debug ]================================
/opt/clion-2018.3.1/bin/cmake/linux/bin/cmake --build /home/ramb/Projects/test_dpi/cmake-build-debug --target test_dpi -- -j 2
[ 50%] Linking CXX executable test_dpi
/usr/bin/ld: CMakeFiles/test_dpi.dir/main.cpp.o: in function `main':
/home/ramb/Projects/test_dpi/main.cpp:9: undefined reference to `DPI::dump(std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, DPI::Dump const&)'
/usr/bin/ld: CMakeFiles/test_dpi.dir/main.cpp.o: in function `boost::system::error_category::std_category::equivalent(int, std::error_condition const&) const':
/usr/include/boost/system/error_code.hpp:676: undefined reference to `boost::system::generic_category()'
/usr/bin/ld: /usr/include/boost/system/error_code.hpp:679: undefined reference to `boost::system::generic_category()'
/usr/bin/ld: CMakeFiles/test_dpi.dir/main.cpp.o: in function `boost::system::error_category::std_category::equivalent(std::error_code const&, int) const':
/usr/include/boost/system/error_code.hpp:706: undefined reference to `boost::system::generic_category()'
/usr/bin/ld: /usr/include/boost/system/error_code.hpp:709: undefined reference to `boost::system::generic_category()'
/usr/bin/ld: /usr/include/boost/system/error_code.hpp:721: undefined reference to `boost::system::generic_category()'
collect2: error: ld returned 1 exit status
gmake[3]: *** [CMakeFiles/test_dpi.dir/build.make:84: test_dpi] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/test_dpi.dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/test_dpi.dir/rule] Error 2
gmake: *** [Makefile:118: test_dpi] Error 2

Что я делаю не так?


Ответ на: комментарий от anonymous

Пока твоя наколенная поделка не превратилась в продающийся продукт…

Хотя, конечно, зависит от системы сборки.

Имхо, по крайней мере - это явно не должно быть определяющим фактором при выборе.

pon4ik ★★★★★ ()
Ответ на: комментарий от pon4ik

Поддержка в IDE это следствие, а причина в том что CMake это стандарт (к сожалению, только де-факто). Вот поэтому и надо выбирать его, а не маргинальные поделки типа meson, закономерно не поддерживаемые ничем.

slovazap ★★★★★ ()
Ответ на: комментарий от slovazap

Когда оно везде насованно - легко кричать стандарт. На старте как ни странно кроме QtC очень и очень долго не было поддержки чуть менее чем нигде.

А то, что в CMake куча страшненького легаси первопроходца (например фикстуры), это медицинский факт. Другое дело что ни одна из альтернатив пока не развилась до нужного уровня.

Другой пример - git/svn. Гуйни под git адекватной тоже довольно долго небыло, а уж чего-то сравнимого со smartSVN и до сих пор имхо нет (smartGIT знаю, но не то это, по крайней мере субъективно).

pon4ik ★★★★★ ()
Ответ на: комментарий от VarfolomeyKote4ka

Кстати интересно, в апстриме gnomebuilder уже есть какая то поддержка meson? Оно хоть и вырвиглазное, но идеи там интересные, плюс в браузере легко запустить.

pon4ik ★★★★★ ()
Ответ на: комментарий от slovazap

Кстати, интересно, почему народ столько извращается…, чего ему на CMake который жаль, что не стандарт не пишется?

Наверное потому, что любая более менее сложная поделка всё равно обрастает кастомными таргетами на пайтоне.

pon4ik ★★★★★ ()
Ответ на: комментарий от pon4ik

Ты прям мастер тавтологий.

На старте как ни странно кроме QtC очень и очень долго не было поддержки чуть менее чем нигде.

Странно было бы если бы где-то была поддержка чего-то на его старте.

А то, что в CMake куча страшненького легаси первопроходца (например фикстуры), это медицинский факт

Странно если бы в проекте с 20 летней историей не было бы легаси.

Кстати, интересно, почему народ столько извращается

Странно что извращенцы извращаются. Помня сколько было врапперов в/из cmake, не удивлён. Равно не удивлён что есть или скоро появится и обратный враппер.

slovazap ★★★★★ ()
Ответ на: комментарий от EXL

Сделал последнюю строку проектного CMakeLists.txt вот такой

target_link_libraries(test_dpi  boost_system boost_serialization boost_wserialization dpi)

поменялся выхлоп линковки

====================[ Build | test_dpi | Debug ]================================
/opt/clion-2018.3.1/bin/cmake/linux/bin/cmake --build /home/ramb/Projects/test_dpi/cmake-build-debug --target test_dpi -- -j 2
[ 60%] Built target dpi
[ 80%] Linking CXX executable test_dpi
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_oprimitive<boost::archive::binary_woarchive, wchar_t, std::char_traits<wchar_t> >::init()'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::filesystem::path_traits::convert(wchar_t const*, wchar_t const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::codecvt<wchar_t, char, __mbstate_t> const&)'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `void DPI::Dump::serialize<boost::archive::binary_woarchive>(boost::archive::binary_woarchive&, unsigned int)'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_oprimitive<boost::archive::binary_woarchive, wchar_t, std::char_traits<wchar_t> >::basic_binary_oprimitive(std::basic_streambuf<wchar_t, std::char_traits<wchar_t> >&, bool)'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_iprimitive<boost::archive::binary_wiarchive, wchar_t, std::char_traits<wchar_t> >::basic_binary_iprimitive(std::basic_streambuf<wchar_t, std::char_traits<wchar_t> >&, bool)'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_oarchive<boost::archive::binary_woarchive>::init()'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_iprimitive<boost::archive::binary_wiarchive, wchar_t, std::char_traits<wchar_t> >::~basic_binary_iprimitive()'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_oprimitive<boost::archive::binary_woarchive, wchar_t, std::char_traits<wchar_t> >::~basic_binary_oprimitive()'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::filesystem::path::codecvt()'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_iarchive<boost::archive::binary_wiarchive>::init()'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `void DPI::Dump::serialize<boost::archive::binary_wiarchive>(boost::archive::binary_wiarchive&, unsigned int)'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_iarchive<boost::archive::binary_wiarchive>::load_override(boost::archive::class_name_type&)'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_oprimitive<boost::archive::binary_woarchive, wchar_t, std::char_traits<wchar_t> >::save(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: dpi/libdpi.so: undefined reference to `boost::archive::basic_binary_iprimitive<boost::archive::binary_wiarchive, wchar_t, std::char_traits<wchar_t> >::init()'
collect2: error: ld returned 1 exit status
gmake[3]: *** [CMakeFiles/test_dpi.dir/build.make:85: test_dpi] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/test_dpi.dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/test_dpi.dir/rule] Error 2
gmake: *** [Makefile:118: test_dpi] Error 2

Причем нет разницы dpi сразу после test_dpi, или после бустовых либ

Ram-B ()
Ответ на: комментарий от slovazap

Ну т.е. история повторяется. Вопрос зачем народ выдумывает новое? Ведь аутотулс тоже норм был бы если бы не вижалстудия. Вон spidermonkey поди до сих пор ими под винду нормально собирается…

Я не говорю что надо сразу на помойку, я лишь отмечаю, что поддержка в IDE это лишь один из факторов, и не самый важный, при выборе системы сборки. Да, на это нужно обратить внимание и да это перевесит при прочих равных.

Вот относительно показательный пример - ты стартуешь проект linux-only. CMake - нельзя, ну х3 почему, такое условие задачи. Что выберешь - automake(есть поддержка во многих IDE, куча доки) или meson?

pon4ik ★★★★★ ()
Ответ на: комментарий от Torvus

Реализация есть в соответствующих .cpp файлах. typedefs.cpp

#include "typedefs.h"

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>

template <typename Ar> void DPI::Packet::serialize(Ar& ar, const unsigned version) {
    ar & BOOST_SERIALIZATION_NVP(flow_id);
}

template <typename Ar> void DPI::Flow::serialize(Ar &ar, const unsigned int version) {
    ar & BOOST_SERIALIZATION_NVP(id);
}

template <typename Ar> void DPI::Dump::serialize(Ar &ar, const unsigned int version) {
    ar & BOOST_SERIALIZATION_NVP(packets);
    ar & BOOST_SERIALIZATION_NVP(flows);
}

streams.cpp

#include "streams.h"

#include <fstream>

bool DPI::dump(const std::wstring &path, const DPI::Dump &dump) {
    boost::filesystem::wofstream file(path);
    boost::archive::binary_woarchive woa(file);

    woa << dump;

    return true;
}

bool DPI::load(const std::wstring &path, DPI::Dump &dump) {
    boost::filesystem::wifstream file(path);
    boost::archive::binary_wiarchive wia(file);

    wia >> dump;

    return true
}
Ram-B ()
Ответ на: комментарий от Ram-B

Там по ссылке 2 параграфа. Если чукча настолько не читатель, то лично я за бан.

Например, ты зачем то ищещь буст, а потом пытаешься по системным путям либы напрямую добавить, а буст мог вообще другой найтись.

Ладно так дикие люди 10 лет назад делали, когда cmake ещё в диковинку местами был. До сих пор отголоски в древних репо попадаются. Но сейчас то и туториалов куча и дока у них торт, даже по многим модулям дока есть…

pon4ik ★★★★★ ()
Ответ на: комментарий от pon4ik

Ведь аутотулс тоже норм был бы

autocrap никогда не был «норм», ибо был и есть нагромождение костылей на недомакроязыке, в котором невозможно разобраться и заставить работать правильно. Его ненавидели когда альтернатив не было. Поэтому ненадолго выстрелил SCons. Но оказался, к сожалению, не системой сборки.

если бы не вижалстудия

На вижуалстудию было, есть и будет всем похрен. Напомню что до появления VS code который типа-кросплатформенен, она была только под винду, и никто из разработчиков СПО её в глаза не видел. Если бы CMake её не умел, стандартом он бы быть не перестал. Но он умеет по той же причине по которой стал стандартом - он выполняющая свои задачи, мощная система сборки.

под винду нормально собирается

Вообще-то autocrap не умеет винду от слова совсем. Единственный способ что-то на нём там собрать - притащить чуждое окружение в виде mingw.

Вот относительно показательный пример - CMake - нельзя, ну х3 почему

Не буду даже комментировать.

slovazap ★★★★★ ()
Ответ на: комментарий от slovazap

На вижуалстудию было, есть и будет всем нищебродам похрен.

fxd.

Вообще-то autocrap не умеет винду от слова совсем.

Скажи это авторам mingw, cygwin и тормозилле.

pon4ik ★★★★★ ()
Ответ на: комментарий от slovazap

CMake никогда не был «норм», ибо был и есть нагромождение костылей на недоDSL.

Очевидный фикс. Одно говно – аутотулзы, заменили другим сортом говна – CMake’ом. Хорошо, что сейчас есть выбор и RedHat, например, к херам послал CMake-наркоманов.

EXL ★★★★★ ()
Ответ на: комментарий от pon4ik

На вижуалстудию было, есть и будет всем нищебродам похрен

Каким это боком? СПО определяют его разработчики, а разработчики СПО используют СПО, так что вижуалстудия пролетает даже будучи бесплатной.

Скажи это авторам mingw, cygwin

Я про это вообще-то написал, только тебе важнее ляпнуть что-нибудь чем прочитать.

slovazap ★★★★★ ()
Ответ на: комментарий от EXL

Хорошо, что сейчас есть выбор и RedHat, например, к херам послал CMake-наркоманов

RedHat’ом можно разве что подтереться, как и твоим неосиляторским мнением. Достаточно сравнить сколько проектов у вас с редхатом в сумме и сколько проектов используют CMake.

slovazap ★★★★★ ()

Ты не можешь свой проект выложить на какой-нибудь гитхаб? Глазами разбираться в куче файла, еще и накладывая правки довольно запарно.

anonymous ()

tl;dr

Я делаю так:

set( Boost_USE_MULTITHREADED ON )
find_package(
    Boost 1.60 REQUIRED
    COMPONENTS
    chrono
    filesystem
    regex
    system
    thread
    program_options
    random
)

link_directories(${Boost_LIBRARY_DIRS}) #<- совсем не обязательно

include_directories(${Boost_INCLUDE_DIRS})

target_link_libraries(
    target
    ${Boost_SYSTEM_LIBRARY}
    ${Boost_FILESYSTEM_LIBRARY}
    ${Boost_REGEX_LIBRARY}
    ${Boost_THREAD_LIBRARY}
    ${Boost_CHRONO_LIBRARY}
    ...
)

WatchCat ★★★★★ ()
Последнее исправление: WatchCat (всего исправлений: 2)
Ответ на: комментарий от slovazap

А каким боком СПО к крупным и сложным системам, за редкими исключениями типа ядра или ceph? В силу модели разработки и требований к срокам, там если и борются со сложностями поддержки и портирования, то на другом уровне в основном.

Я про это вообще-то написал, только тебе важнее ляпнуть что-нибудь чем прочитать.

Вот сиё и правда ускользнуло от моего глаза.

pon4ik ★★★★★ ()
Ответ на: комментарий от Torvus

А вот и не обязательно. Инстанцировать шаблон можно в любой точке после объявления. Просто без определения в хидере, не выйдет инстанцировать шаблон для типов которые не предусмотрел автор, что тоже не всегда плохо, если цель надавать по рукам пользователю в случае шага влево.

pon4ik ★★★★★ ()
Последнее исправление: pon4ik (всего исправлений: 1)