Неопределенная ссылка в clang при ссылке на библиотеку, скомпилированную с GCC5

Я пытаюсь использовать версию libmuparser для репозитория Ubuntu 15.10 (пакет libmuparser2v5). Компиляция с gcc работает нормально, но не с clang. Я углубился в это, чтобы придумать следующий минимальный (не) рабочий пример и несколько вопросов.

Рассмотрим библиотеку с простым классом, который принимает string и возвращает string,

testlib.h:

#pragma once

#include <string>

struct Test {
std::string str;

void set(std::string s);
std::string get();
};

testlib.cpp:

#include "testlib.h"
void Test::set(std::string s) {
str = s;
}

std::string Test::get() {
return str;
}

Это скомпилировано с gcc 5.2.1 как статическая библиотека с

g++ -Wall -c testlib.cpp -o testlib-gcc.o
ar rcs libtest-gcc.a testlib-gcc.o

Сейчас компилируем приложение main.cpp

#include <iostream>
#include "testlib.h"
int main()
{
Test p;
p.set("Hello!");
std::cout << p.get() << std::endl;
return 0;
}

с лязгом 3.6.2-1 с помощью

clang++ main.cpp -o out-clang libtest-gcc.a

приводит к ошибке

main.cpp:(.text+0x79): undefined reference to `Test::get()'

Теперь я обнаружил, что в gcc5 появилась новая функция, называемая тегами ABI, которая помогает управлять версиями библиотек и предотвращать ссылки, когда они несовместимы. Глядя на статическую библиотеку

$ nm -gC libtest-gcc.a

дает:

testlib-gcc.o:
0000000000000026 T Test::get[abi:cxx11]()
0000000000000000 T Test::set(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)

Так что тег ABI cxx11 был добавлен для get но не для set, Тег, по-видимому, добавляется, когда метод возвращает string, Вот почему Clang утверждает только о том, что не нашел Test::get(),

Я думаю, это сделано, чтобы дать get вызывающая подпись, которая дает понять, что c ++ 11 требуется для связи с этой функцией. За set это не обязательно, из-за __cxx11 в типе.

Вопросы:

  • Я прав в своем предположении или есть что-то еще, что можно добавить?
  • Если так, как это исправить?
    • Что может писатель библиотеки сделать библиотеку связываемой как с компилированным кодом gcc 5.2, так и clang 3.6? (Исходный код меняется?)
    • Что может пользователь библиотеки сделать, чтобы скомпилировать и связать clang 3.6 с библиотекой, скомпилированной с gcc 5.2 или наоборот. (Изменения исходного кода или флаги компиляции?)
    • Что может сопровождающий сделать библиотеку связываемой как с компилированным кодом gcc 5.2, так и clang 3.6? (Флаги компиляции?)
    • Будет ли это исправлено разработчики лязг в будущей версии (какая версия)? (Совместимость ABI по умолчанию?) Однако было бы неплохо найти решение сейчас, так как в противном случае clang сложно использовать в Ubuntu 15.10 и его производных.

Дополнительная информация:

  • Подпись get определяется, когда testlib.cpp компилируется. Таким образом, общий объект не будет иметь никакого значения. Можно также использовать nm -gC testlib-gcc.o чтобы увидеть символы.
  • В библиотеке с clang подпись get является Test::get(), Тогда GCC не может найти символ Test::get[abi:cxx11]()совместимость нарушена.
  • Использование флага компиляции -D_GLIBCXX_USE_CXX11_ABI=0 для gcc (найдено Вот) не является решением, так как тогда сигнатура множества также изменяется: Test::set(std::string) (но get хорошо тогда).
  • Использование флага компиляции -stdlib=libc++ в Clang, кажется, не помогает, так как он также сообщает неопределенную ссылку на Test::get() (и много других неопределенных ссылок).

8

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]