如何使用CMake正确链接cpp中的模块

问题描述 投票:0回答:1

我开始学习 C++,CMake 对我来说是一个更大的困难。 我已经编写了一些代码来帮助我开始,并且还想从一开始就编写测试。 除了每次运行测试时我都会得到未定义的符号。

我已经在 test.cp 中包含#include“ConfigStore.h”并且该文件似乎已被识别

编译时出错:

[build] ld: Undefined symbols:
[build]  ConfigStore::addValue(std::__1::basic_string<char, std::__1::char_traits<char>
...
[build] clang: error: linker command failed with exit code 

这就是我的制作方法:

项目结构

根:

CMakeLists.txt

根/基础设施/ConfigStore:

ConfigStore.h /ConfigStore.cpp ->(包括“../Singleton/Singleton.h”)

CMakeLists.txt

根/基础设施/单例:

Singleton.h / Singleton.cpp

根/测试

CMakeLists.txt 谷歌测试 ConfigStore_test.cpp

为了简洁起见,以下是我如何将 ConfigStore 添加到我的测试项目中。

CMakeLists(测试):

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/googletest/include ${CMAKE_SOURCE_DIR}/Infrastructure/ConfigStore)
link_directories(${BinanceAPI_LIB_OUT}/ConfigStore)

在 CMakeLists.txt 中:




set(LIBRARY_OUTPUT_PATH ${BinanceAPI_LIB_OUT}/${PROJECT_NAME})
set(CONFIG_STORE_DIR ${CMAKE_CURRENT_SOURCE_DIR})

add_library(${PROJECT_NAME} SHARED ConfigStore)```

还有根 CMakeLists.txt :

add_subdirectory(${CMAKE_SOURCE_DIR}/Infrastructure/ConfigStore)
add_subdirectory(test)

add_library(BinanceAPI BinanceAPI.cpp)

target_link_libraries(${PROJECT_NAME} PUBLIC 
ConfigStore)```

编辑

以下是 .h 和 .cpp 文件中的内容:

ConfigStore.h

#ifndef CONFIGSTORE
#define CONFIGSTORE


#include "../Singleton/Singleton_H"
#include<map>
#include<fstream>
#include<string>

typedef std::map<std::string,std::string> t_Store;

class ConfigStore final : public Singleton<ConfigStore>
{
    
    
private:
 t_Store m_StoredConfig;

public:
    ConfigStore(token){ }
    ~ConfigStore() {}
    void parseFile(std::ifstream& p_inStream);
    void addValue(std::string key,std::string value);
    std::string getValue(std::string key);
};

#endif // CONFIGSTORE

ConfigStore.cpp

#include "ConfigStore.h"



void ConfigStore::addValue(std::string key, std::string value){
    auto[it,result] = m_StoredConfig.try_emplace(key,value);
    if(!result){
        //error management
    }
}

std::string ConfigStore::getValue(std::string key){
    auto pos = m_StoredConfig.find(key);
    if(pos == m_StoredConfig.end()){
        return "";
    } else {
        return pos->second;
    }

}

单例.h:


#ifndef SINGLETON
#define SINGLETON

template<typename T>
class Singleton
{
public:
    static T& instance();

    Singleton(const Singleton&) = delete;
    Singleton& operator= (const Singleton) = delete;

protected:
    struct token {};
    Singleton() {};
};

#endif // SINGLETON

单例.cpp

#include "Singleton.h"
#include <memory>


template<typename T>
T& Singleton<T>::instance(){
    static const std::unique_ptr<T> instance{new T{}};
    return *instance;

}


最后是 ConfigStore_test.cpp:

#include <gtest/gtest.h>
#include "ConfigStore_H"

TEST(ConfigStoreTest, ConstructTest){
    auto &config = ConfigStore::instance();
    std::string value = "t";
    config.addValue("test",value);
    EXPECT_EQ(value,config.getValue("test"));
}

我知道这是很多代码,但我真的很难找出问题所在。感谢您的帮助!

c++ cmake googletest cmakelists-options cmake-language
1个回答
0
投票

有两个问题阻止此设置工作:

I - 未正确命名头文件 :

我所有的头文件都没有'.h'扩展名,我只是在最后添加了_H。这并没有阻止 Intellisense 工作,但 CMake 并不高兴。

这解决了与 ConfigStore 相关的所有未定义符号。

我在 main 中留下了一个未定义的符号。

II - 未正确导入 Gtest:gtest_main :

由于我使用 GTest 来编写单元测试,因此我不必编写 main.相反,GTest 作为处理测试入口点的 gtest_main 方法。

所以代替:

target_link_libraries(
    ConfigStore_Test PUBLIC
    gtest
    ConfigStore
)

我用过这个:

target_link_libraries(
    ConfigStore_Test PUBLIC
    GTest::gtest_main
    ConfigStore
)
© www.soinside.com 2019 - 2024. All rights reserved.