簡體   English   中英

使用CMake鏈接到Windows上的靜態庫的麻煩

[英]Troubles linking to a static library on windows with CMake

LS,

我正在嘗試構建一個靜態和動態庫,可用於動態和靜態鏈接。 無論使用何種編譯器,我都希望該庫能夠在盡可能多的平台上運行。 為了構建庫和一些測試程序,我正在使用CMake在Linux和Windows上分別使用g ++和MSVC ++構建庫eeg。

在Linux上,動態和靜態庫似乎都像我懷疑的那樣工作,在Windows上.dll似乎完美地鏈接並且我的測試程序運行。 但是,使用靜態庫的程序會抱怨鏈接錯誤。 我真的很想念我做錯了什么,它可能是我的CMakeLists.txt中的內容,也可能是我的庫的安裝程序。 下面我做了一個使用我的庫的最小程序,它演示了我遇到的問題。 該庫包含兩個C ++文件,一個用於導出C ++文件中的代碼的C API,一個使用C API的C ++程序,以及一個可以構建所有程序但使用靜態庫的程序的CMakeList.txt。 這一切都產生了一個美妙的“你好,世界!”。

我知道我展示了很多代碼,但至少它是一個最小的項目,它演示了我鏈接到靜態庫的問題。 我希望有人能夠看看這個項目並向我解釋我做錯了什么。

親切的問候,

hetepeperfan

C ++文件PriCpp.cpp

#include "PriCpp.h"

using namespace std;
string PriMessageBuilder::message() const {
    return "Hello, World!";
}

標題PriCpp.h

#ifndef PRICPP_H
#define PRICPP_H

#include <string>

class PriMessageBuilder{
public:
    std::string message() const;
};

#endif

C API是:mycapi.h

#ifndef MYCAPI_H
#define MYCAPI_H
#include "builder_export.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {} message_builder;

BUILDER_EXPORT message_builder* message_builder_new();
BUILDER_EXPORT void             message_builder_destroy(
                                        message_builder* builder
                                        );
BUILDER_EXPORT char*            message_builder_message(
                                        message_builder* builder
                                        );
#ifdef __cplusplus
}
#endif

#endif

mycapi.cpp是:

#include "mycapi.h"
#include "PriCpp.h"
#include <cstring>
#include <cstdlib>

message_builder* message_builder_new() {
    PriMessageBuilder* ret = NULL;
    try {
        ret = new PriMessageBuilder();
    } catch (...) {
    }
    return reinterpret_cast<message_builder*>(ret);
}

void message_builder_destroy(message_builder* builder)
{
    PriMessageBuilder* b = reinterpret_cast<PriMessageBuilder*>(builder);
    delete b;
}

char* message_builder_message(message_builder* builder)
{
    PriMessageBuilder* b = reinterpret_cast<PriMessageBuilder*>(builder);
    return strdup(b->message().c_str());
}

我與上面的庫結合使用的程序。 program.cpp

#include <iostream>
#include <cstdlib>
#include <string>
#include "mycapi.h"

using namespace std;

class MessageBuilder {
public:
    MessageBuilder() : m_builder(message_builder_new()) {
    }
    ~MessageBuilder() {
        message_builder_destroy(m_builder);
    }
    string MessageBuilder::message() {
        char* msg = message_builder_message(m_builder);
        string m(msg);
        free (msg);
        return m;
    }
private:
    message_builder* m_builder;
};

int main(int, char**) {
    MessageBuilder m;
    cout << m.message() << endl;
    return 0;
}

最后是CMakeLists.txt來構建makefile或visual studio解決方案

#setting up project
cmake_minimum_required(VERSION 2.6)
project(libbuilder CXX) 
include (GenerateExportHeader)

include_directories("${PROJECT_BINARY_DIR}")

#creating library
add_library(builder SHARED PriCpp.cpp PriCpp.h mycapi.cpp mycapi.h)
add_library(builder-static STATIC PriCpp.cpp PriCpp.h mycapi.cpp mycapi.h)

generate_export_header(builder)

set_target_properties(builder PROPERTIES COMPILE_FLAGS -DBUILD_BUILDER_SHARED)
set_target_properties(builder-static PROPERTIES COMPILE_FLAGS -DBUILDER_STATIC_DEFINE)

#creating programs
add_executable(program program.cpp)
add_executable(program-static program.cpp)

target_link_libraries(program builder)
target_link_libraries(program-static builder-static)

如果我構建解決方案,我會收到這些鏈接器錯誤:

1>program.obj : error LNK2019: unresolved external symbol __imp__message_builder_new referenced in function "public: __thiscall MessageBuilder::MessageBuilder(void)" (??0MessageBuilder@@QAE@XZ)
1>program.obj : error LNK2019: unresolved external symbol __imp__message_builder_destroy referenced in function "public: __thiscall MessageBuilder::~MessageBuilder(void)" (??1MessageBuilder@@QAE@XZ)
1>program.obj : error LNK2019: unresolved external symbol __imp__message_builder_message referenced in function "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall MessageBuilder::message(void)" (?message@MessageBuilder@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>K:\duijn119\programming\cmake\staticsharedlib\build\Debug\program-static.exe : fatal error LNK1120: 3 unresolved externals

CMake生成的包含頭是:

#ifndef BUILDER_EXPORT_H
#define BUILDER_EXPORT_H

#ifdef BUILDER_STATIC_DEFINE
#  define BUILDER_EXPORT
#  define BUILDER_NO_EXPORT
#else
#  ifndef BUILDER_EXPORT
#    ifdef builder_EXPORTS
        /* We are building this library */
#      define BUILDER_EXPORT __declspec(dllexport)
#    else
        /* We are using this library */
#      define BUILDER_EXPORT __declspec(dllimport)
#    endif
#  endif

#  ifndef BUILDER_NO_EXPORT
#    define BUILDER_NO_EXPORT 
#  endif
#endif

#ifndef BUILDER_DEPRECATED
#  define BUILDER_DEPRECATED __declspec(deprecated)
#endif

#ifndef BUILDER_DEPRECATED_EXPORT
#  define BUILDER_DEPRECATED_EXPORT BUILDER_EXPORT BUILDER_DEPRECATED
#endif

#ifndef BUILDER_DEPRECATED_NO_EXPORT
#  define BUILDER_DEPRECATED_NO_EXPORT BUILDER_NO_EXPORT BUILDER_DEPRECATED
#endif

#define DEFINE_NO_DEPRECATED 0
#if DEFINE_NO_DEPRECATED
# define BUILDER_NO_DEPRECATED
#endif

#endif

您需要在add_executable(program-static program.cpp)之后添加set_target_properties(program-static PROPERTIES COMPILE_FLAGS -DBUILDER_STATIC_DEFINE) add_executable(program-static program.cpp) 目前你的靜態庫正確構建,但應用程序獲取了帶有錯誤declspec的庫頭(好吧,根本就沒有declspec ,你有一個)

此外,使用以下概念似乎更合適:

set_target_properties(program-static PROPERTIES COMPILE_DEFINITIONS BUILDER_STATIC_DEFINE)

COMPILE_DEFINITIONS而不是COMPILE_FLAGS

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM