Отслеживание проблемы с -fvisibility=hidden, которая вызывает неопределенную ссылку на `typeinfo for myfunc'

Я пытаюсь скомпилировать проект, написанный на переносимом C++. Он прекрасно компилируется с Visual Studio 2010 в Windows 7 и использует макросы видимости символов.

Однако, когда я компилирую этот проект с gcc-4.7 в Linux, я получаю эту ошибку компоновщика:

g++ -fvisibility=hidden -fvisibility-inlines-hidden [...]
/tmp/ccegevbt.o:(.rodata._ZTI12subclass[_ZTI12subclass]+0x10): undefined reference to `typeinfo for ns::baseclass'

Я прочитал предыдущий отчет и, действительно, экспорт на уровне класса напрямую (вместо каждого символа) решает симптомы, и я хотел бы понять, почему он не работает на уровне символов:

class __attribute__ ((visibility ("default"))) baseclass {

Однако на самом деле код написан для экспорта только некоторой функции-члена, поэтому он должен производить идентичное поведение с компилятором Visual Studio C++, верно?

class baseclass {
public: // Member functions
  DLL_EXPORT baseclass();
  DLL_EXPORT virtual ~baseclass();

Мой вопрос: что немного отличается поведение при экспорте символов между Visual Studio 2010 и gcc-4.7? Как я могу отследить, какой символ на самом деле вызывает проблему?

Для пояснения приведу очень маленький пример с игрушкой, который отлично работает на Visual Studio 2010.

$ cat test.h
#pragma once

#ifdef __GNUC__
#define DLL_EXPORT __attribute__((visibility("default"))) 
#else
#define DLL_EXPORT  __declspec(dllexport)
#endif

struct Base
{
    DLL_EXPORT virtual ~Base();
    DLL_EXPORT virtual Base* clone() {
        return 0;
    }
};

#undef DLL_EXPORT

а также

$ cat test.cpp
#include "test.h"

Base::~Base()
{
}

а также

$ cat main.cpp
#include "test.h"

struct Foo : public Base
{
    virtual ~Foo();
    virtual Base* clone() {
        return new Foo();
    }
};

Foo::~Foo()
{
}

int main()
{
    Base* f = new Foo();
    f->clone();
    return 0;
}

используя cmake, это просто:

$ cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(bla)

add_library(test SHARED test.cpp)
add_executable(main main.cpp)
target_link_libraries(main test)

Из Linux:

$ export CXXFLAGS="-fvisibility=hidden -fvisibility-inlines-hidden"
$ cmake . && make

Из окон:

$ cmake . -G"NMake Makefiles"
$ nmake

Для людей, не использующих cmake, вы можете использовать:

$ cat Makefile
main: main.cpp test.h libtest.so
    g++ -fvisibility=hidden -fvisibility-inlines-hidden -L. -ltest main.cpp -o main
libtest.so: test.cpp test.h
    g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC -shared test.cpp -o libtest.so

что приводит к:

$ make
g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC -shared test.cpp -o libtest.so
g++ -fvisibility=hidden -fvisibility-inlines-hidden -L. -ltest main.cpp -o main
/tmp/cc5lGsdn.o: In function `Base::Base()':
main.cpp:(.text._ZN4BaseC2Ev[_ZN4BaseC5Ev]+0xf): undefined reference to `vtable for Base'
/tmp/cc5lGsdn.o:(.rodata._ZTI3Foo[_ZTI3Foo]+0x10): undefined reference to `typeinfo for Base'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1

В случае, если это имеет значение, добавление -fno-devirtualize не помогает (согласно sug отсюда)

0 ответов

Другие вопросы по тегам