Я пытаюсь использовать версию 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
в типе.
Вопросы:
Дополнительная информация:
get
определяется, когда testlib.cpp
компилируется. Таким образом, общий объект не будет иметь никакого значения. Можно также использовать nm -gC testlib-gcc.o
чтобы увидеть символы.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()
(и много других неопределенных ссылок).Задача ещё не решена.
Других решений пока нет …