首页 > 解决方案 > C++ 模块化项目链接问题和未定义的引用错误

问题描述

我无法弄清楚如何构建模块化的 C++ 应用程序并让所有内容正确连接。具体来说,我无法构建一些测试,因为最终我得到一个基于类方法的未定义引用错误。(我是 C++ 和 CMake 的新手,所以我可能做错了很多,但我正在学习!)我浏览过其他帖子,我所能收集到的只是我可能没有正确链接。

OrderBook 和 Strategy 都构建得很好。但是,当我去构建 StrategyTests 和 OrderBookTests 时,我得到一个错误:

[ 83%] Linking CXX executable StrategyTests.exe
../../OrderBook/libOrderBook.a(OrderBook.cpp.o): In function `orderbook::OrderBook::notify_strategies(std::shared_ptr<orderbook::Order> const&, bool)':
/cygdrive/d/Dropbox/My Documents/Programming/CLionProjects/TradingSystem/OrderBook/OrderBook.cpp:220: undefined reference to `HYSTRAT::Strategy::onBookUpdate(std::shared_ptr<Events::TOB> const&, std::shared_ptr<Events::OrderBookEvent> const&, bool)'
/cygdrive/d/Dropbox/My Documents/Programming/CLionProjects/TradingSystem/OrderBook/OrderBook.cpp:220:(.text+0x11c4): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `HYSTRAT::Strategy::onBookUpdate(std::shared_ptr<Events::TOB> const&, std::shared_ptr<Events::OrderBookEvent> const&, bool)'
collect2: error: ld returned 1 exit status

我尝试了许多不同的方法,包括摆弄 CMakeLists 和标头,但似乎都不起作用。很明显,我不知道“未定义引用”的真正含义。我怀疑这是一个简单的解决方法,但我在下面发布了项目设置以防万一。

这是我的设置:

Windows 10 上的 Clion 和 Cygwin

项目树

TradingSystem
|-CMakeLists.txt
|\OrderBook
|-|-CMakeLists.txt
|-|-OrderBook.h
|-|-OrderBook.cpp
|\Strategy
|-|-CMakeLists.txt
|-|-Strategy.h
|-|-Strategy.cpp
|\Tests
|-|-CMakeLists.txt
|-|\OrderBookTests
|-|-|-CMakeLists.txt
|-|-|\BoostTests
|-|-|-|-CMakeLists.txt
|-|-|-|-OrderBookBoostTests.cpp
|-|\StrategyTests
|-|-|-CMakeLists.txt
|-|-|-StrategyBoostTests.cpp

CMakes

#TradingSystem/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(TradingSystem)

set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES main.cpp)

add_executable(TradingSystem ${SOURCE_FILES} ${HEADER_FILES})

include_directories(OrderBook Strategy Events)

add_subdirectory(OrderBook)
add_subdirectory(Strategy)
add_subdirectory(Events)
add_subdirectory(Tests/OrderBookTests)
add_subdirectory(Tests/StrategyTests)

target_link_libraries(TradingSystem OrderBook Strategy)

-

#TradingSystem/OrderBook/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(OrderBook)

include_directories(/cygdrive/c/Program Files/boost/boost_1_66_0)

set(CMAKE_CXX_STANDARD 11)
set(HEADER_FILES OrderBook.h)
set(SOURCE_FILES OrderBook.cpp)

add_library(OrderBook STATIC ${SOURCE_FILES} ${HEADER_FILES})

-

#TradingSystem/Strategy/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Strategy)

include_directories(/cygdrive/c/Program Files/boost/boost_1_66_0)

set(CMAKE_CXX_STANDARD 11)
set(HEADER_FILES Strategy.h)
set(SOURCE_FILES Strategy.cpp)

add_library(Strategy STATIC ${SOURCE_FILES} ${HEADER_FILES})

-

#TradingSystem/Tests/CMakeLists.txt
project(Tests)
add_subdirectory(OrderBookTests)
add_subdirectory(StrategyTests)

-

#TradingSystem/Tests/OrderBookTests/CMakeLists.txt
project(OrderBookTests)
add_subdirectory(BoostTests)

[编辑]

#TradingSystem/Tests/OrderBookTests/BoostTests/CMakeLists.txt
add_executable(BoostTests OrderBookBoostTests.cpp)

enable_testing()
include_directories(/cygdrive/c/Program Files/boost_1_66_0)

set(BOOST_ROOT "C:/Program Files/boost_1_66_0/")
set(BOOST_LIBRARYDIR "C:/Program Files/boost_1_66_0/")

find_package(Boost 1.66.0)

find_package(Boost COMPONENTS unit_test_framework REQUIRED)

include_directories(${BOOSTROOT})
link_directories("${BOOSTROOT}")
target_include_directories(OrderBook PRIVATE ${BOOST_INCLUDE_DIRS})

# Original:
# target_link_libraries(BoostTests OrderBook)
# Changed to: 
target_link_libraries(BoostTests Orderbook Strategy)

if(NOT Boost_FOUND)
    message(FATAL_ERROR "Could not find boost!")
endif()

[编辑]

#TradingSystem/Tests/StrategyTests/CMakeLists.txt
project(StrategyTests)

add_executable(StrategyTests StrategyBoostTests.cpp)

enable_testing()
include_directories(/cygdrive/c/Program Files/boost_1_66_0)

set(BOOST_ROOT "C:/Program Files/boost_1_66_0/")
set(BOOST_LIBRARYDIR "C:/Program Files/boost_1_66_0/")

find_package(Boost 1.66.0)

find_package(Boost COMPONENTS unit_test_framework REQUIRED)

include_directories(${BOOSTROOT})
link_directories("${BOOSTROOT}")
target_include_directories(Strategy PRIVATE ${BOOST_INCLUDE_DIRS})

# Original:
# target_link_libraries(StrategyTests Strategy OrderBook)
# Change to:
target_link_libraries(StrategyTests Orderbook Strategy)

if(NOT Boost_FOUND)
    message(FATAL_ERROR "Could not find boost!")
endif()

源文件

#TradingSystem/OrderBook/OrderBook.h
#fndef TRADINGSYSTEM_ORDERBOOK_H
#define TRADINGSYSTEM_ORDERBOOK_H

#include <vector>
using std::vector;

#include "Strategy.h"
#include "Events.h"

namespace orderbook {
    /////////////////////
    // HIDDEN CODE
    /////////////////////

    class OrderBook {
    private:
        vector<HYSTRAT::Strategy> strategies_;

        bool notify_strategies(const order_ptr& o, bool add_flag);;
        Events::order_book_event_ptr create_order_book_event(const order_ptr& order);;

    public:
        /////////////////////////////
        // CONSTRUTORS; DESTRUCTORS
        /////////////////////////////

        inline bool subscribe(HYSTRAT::Strategy& s) {
            strategies_.push_back(s);
        }

#endif //TRADINGSYSTEM_ORDERBOOK_H

-

#TradingSystem/OrderBook/OrderBook.cpp
#include "OrderBook.h"
#include "Events.h"
#include "Strategy.h"

using orderbook::OrderBook;
using HYSTRAT::Strategy;

bool orderbook::OrderBook::notify_strategies(const order_ptr& o, bool add_flag) {
    try {
        Events::order_book_event_ptr event = create_order_book_event(o);
        Events::topOfBook_ptr tob = get_top_of_book();
        for (HYSTRAT::Strategy& strategy : strategies_) {
            strategy.onBookUpdate(tob, event, add_flag);
        }
        return true;
    } catch (const std::exception& e) {
        return false;
    }
}

-

#TradingSystem/Strategy/Strategy.h
#ifndef TRADINGSYSTEM_STRATEGY_H
#define TRADINGSYSTEM_STRATEGY_H

#include "Events.h"

namespace HYSTRAT {
    class Strategy {
    public:
        void onBookUpdate(const Events::topOfBook_ptr& tob, const Events::order_book_event_ptr& e, bool event_flag);;
    };
}

#endif //TRADINGSYSTEM_STRATEGY_H

-

#TradingSystem/Strategy/Strategy.cpp
#include "OrderBook.h"
#include "Strategy.h"
#include "Events.h"

using namespace HYSTRAT;

void Strategy::onBookUpdate(const Events::topOfBook_ptr &tob, const Events::order_book_event_ptr &e, bool event_flag) {
    if (tob->bidP >= tob->offerP) {
        quantity_t order_size = std::min(tob->offerQ, tob->bidQ);
        order_ptr buy_order(new Order(tob->offerP, order_size, BUY));
        order_ptr sell_order(new Order(tob->bidP, order_size, SELL));
        send_order(buy_order);
        send_order(sell_order);
    }
}

标签: c++cmakelinker-errors

解决方案


我认为您在 CMakeLists.txt 文件中缺少对“add_dependencies”的一些调用。我认为这个特殊问题可以通过添加来解决

add_dependencies(OrderBook Strategy)

到您的订单簿 CMakelists.txt


推荐阅读