Exporting templat instantiations from DLLs.
Given the following example :
CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(export_templates CXX)
include(GenerateExportHeader)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
add_library(mylib SHARED header.hpp mylib.cpp)
generate_export_header(mylib)
add_executable(myexe header.hpp main.cpp)
target_link_libraries(myexe mylib)
header.hpp:
#pragma once
#include <vector>
template<typename T>
struct foo
{
std::size_t bar() {
std::vector<T> t;
t.resize(10);
return t.size();
}
};
extern template struct foo<int>;
mylib.cpp:
#include "header.hpp"
#include <mylib_export.h>
template struct MYLIB_EXPORT foo<int>;
main.cpp:
#include "header.hpp"
int main()
{
foo<int> f;
return f.bar();
}
I get the following linker error:
[ 75%] Linking CXX executable myexe
CMakeFiles/myexe.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x1f): undefined reference to `foo<int>::bar()'
What can I do to get this to link, with the following requirements:
- Should work on linux (.so), macOS (.dylib), windows (.dll)
- With latest gcc, msvc, and clang.
- Without adding
MYLIB_EXPORTto the definition ofstruct foo(since in the real case,struct foois not under my control). - Without suggesting the use of static linking - If I could, I would.
Thanks !
Posted Mar 13, 2018, 6:07 PM UTC
43
I might be wrong, but AFAIK the template types get resolved at compile time, so they can't be used with dynamic linking. Your options are making a header-only lib, using a static link or ditching the template.
no, templates can be resolved at link time: https://godbolt.org/g/PW9acw
in particular, the syntax
template struct foo<int>;does explicit instantiation of the template so that all defined functions be generated: https://godbolt.org/g/ecRwCMYeah, but here the thing is done at compile time. Like with static linking. When you use a dynamic lib linking is done at load time. And you can't resolve templates then.