Проблемы со связью с abi: cxx11 на небольшом проекте - PullRequest
0 голосов
/ 16 октября 2018

Я использую шаблон проекта C ++ из здесь , он использует CMake / Make для сборки проекта и включает в себя много батарей (я довольно новичок в C ++, но не программирую в целом).

Я начал работать над своим проектом, реализовав все в заголовочных файлах, и теперь хочу попробовать мой код.Однако, когда я пытаюсь скомпилировать код (с ./configure и make), я сталкиваюсь со следующей ошибкой во время линковки.

[ 40%] Linking CXX executable ../../bin/projectname
/usr/bin/ld: CMakeFiles/projectname.dir/main.cxx.o: in function `Coordinator::get_price_at(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, boost::gregorian::date)':
/usr/include/c++/8.2.1/bits/unordered_map.h:977: undefined reference to `Coordinator::stocks[abi:cxx11]'
/usr/bin/ld: CMakeFiles/projectname.dir/main.cxx.o: in function `RandomStrategy::rebalance(boost::gregorian::date)':
/usr/include/c++/8.2.1/bits/hashtable.h:1256: undefined reference to `Coordinator::stocks[abi:cxx11]'
/usr/bin/ld: CMakeFiles/projectname.dir/main.cxx.o: in function `Coordinator::read_stock_data(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/usr/include/c++/8.2.1/bits/fs_path.h:183: undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
/usr/bin/ld: CMakeFiles/projectname.dir/main.cxx.o: in function `Coordinator::read_stock_data(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/usr/include/c++/8.2.1/bits/fs_dir.h:356: undefined reference to `std::filesystem::__cxx11::directory_iterator::directory_iterator(std::filesystem::__cxx11::path const&, std::filesystem::directory_options, std::error_code*)'
/usr/bin/ld: CMakeFiles/projectname.dir/main.cxx.o: in function `Coordinator::read_stock_data(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/home/jan/StockAnalyzer/src/Coordinator.h:55: undefined reference to `std::filesystem::__cxx11::directory_iterator::operator*() const'
/usr/bin/ld: CMakeFiles/projectname.dir/main.cxx.o: in function `Coordinator::read_stock_data(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/usr/include/c++/8.2.1/bits/unordered_map.h:977: undefined reference to `Coordinator::stocks[abi:cxx11]'
/usr/bin/ld: CMakeFiles/projectname.dir/main.cxx.o: in function `Coordinator::read_stock_data(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/home/jan/StockAnalyzer/src/Coordinator.h:55: undefined reference to `std::filesystem::__cxx11::directory_iterator::operator++()'
collect2: error: ld returned 1 exit status

После большого количества поисков я попробовал add_definitions(-D_GLIBCXX_USE_CXX11ABI=0) вфайл CMakeLists.txt в базовом каталоге.Я проверил, также добавив -v, это передается gcc.Однако это буквально ничего не меняет.В другом потоке я обнаружил, что вы можете получить ту же ошибку, когда забыли ClassName:: перед доступом к static_variables, поэтому я проверил это (не происходит в соответствующих строках).

Соответствующие частикод:

main.cxx:

#include <cstdlib>
#include <boost/program_options.hpp>
#include "app.h"
#include "Coordinator.h"
#include "RandomStrategy.h"

namespace po = boost::program_options;

po::options_description getDescription() {

    po::options_description desc("Options");
    desc.add_options()
        ("help,h",      "Display this message")
        ("version,v",   "Display the version number");

    return desc;
}

void start() {
    std::string RESOURCES_PATH = "/home/jan/StockAnalyzer/resources/";
    long double investment_money = 50000;
    Coordinator::read_stock_data(RESOURCES_PATH);
    RNGType rng;
    boost::uniform_real<> zero_to_one( 0.0, 1.0 );

    RandomStrategy r(investment_money, rng, zero_to_one);
    Strategy* cur_strat = &r;


}


int main(int argc, char **argv) {
    start();
    return 0;
}

Coordinator.h:

#ifndef SRC_COORDINATOR_H_
#define SRC_COORDINATOR_H_

#include <vector>
#include <unordered_map>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/optional.hpp>
#include <boost/tokenizer.hpp>
#include <fstream>
#include <string>
#include <iostream>
#include <filesystem>
#include "StockData.h"
#include "Utility.h"

class Coordinator {
private:
  static std::unordered_map<std::string, StockData> stocks;

public:
  static StockData get_price_history(const std::string& stock_name) {
    return Coordinator::stocks[stock_name];
  }

  static boost::optional<StockDataPoint> get_price_at(const std::string& stock_name, boost::gregorian::date date) {
    StockData sd = Coordinator::stocks[stock_name];
    for(StockDataPoint sdp : sd.get_price_history()) {
      if(sdp.get_date() == date) {
        return boost::optional<StockDataPoint>(sdp);
      }
    }
    return boost::optional<StockDataPoint>();
  }

  static std::vector<std::string> get_all_stocks() {
    return get_keys(Coordinator::stocks);
  }

  static void read_stock_data(const std::string& path_name) {
    for (auto& file_name : std::filesystem::directory_iterator(path_name)) {
      std::string file_name_string = file_name.path().string();
      StockData cur_data;
      std::vector<StockDataPoint> price_history;
      std::ifstream stock_file(file_name_string);
      std::string line;
      while (std::getline(stock_file, line)) {
        std::vector<std::string> split_input;
        boost::split(split_input, line, [](char c){return c == ',';});
        price_history.push_back(StockDataPoint(split_input));
      }
      cur_data.price_history = std::move(price_history);
      Coordinator::stocks[file_name_string] = cur_data;
    }
  }
};

#endif

Я использую библиотеки повышения и Qt в моем проекте- Boost уже включен, и, поскольку репо 4 года, я подозреваю, что у него может быть эта проблема с Cxx11 ABI.Но, может быть, я просто пропускаю что-то простое в Coordinator.h.Мои .cpp файлы содержат только #include "<File>.h"

1 Ответ

0 голосов
/ 16 октября 2018

Если вы объявляете статический член данных в классе, это аналогично объявлению переменной как extern.Этот код

class Foo {
    static int data;
};

объявляет Foo :: data.Вам необходимо определить переменную как

int Foo:data;

в модуле компиляции.

Ваш элемент данных Coordinator::stocks требует аналогичного определения:

class Coordinator {
private:
  typedef std::unordered_map<std::string, StockData> stocks_t; 
  static stocks_t stocks;      // declaration
};

Coordinator::stocks_t Coordinator::stocks;// definition.

Это исправит ошибку

неопределенная ссылка на `Coordinator :: stocks '

Я использовал шаблон СУХОЙ (не повторяйся) и ввел typedef, чтобы не вводить карту STL дважды.

Редактировать: (Чтобы завершить ответ, на основе комментария, предоставленного OP).

Неразрешенные внешние ссылки

неопределенная ссылка на `std :: filesystem :: ...

можно решить, связав библиотеку stdc++fs.Для этого stdc++fs следует добавить к TARGET_LINK_LIBRARIES в CMakeFile.

...