Bonjour

Ma question est quasiment en tout point identique à celle ci sur stackoverflow qui n'a pas trouvé de réponse: https://stackoverflow.com/questions/...-shared-object

Je reproduis le code pour vous simplifier la vie:

CMakeLists.txt:

Code CMakeLists : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
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)

header.hpp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
#include "header.hpp"
 
#include <mylib_export.h>
template struct MYLIB_EXPORT foo<int>;
- Visual Studio générera une librairie partagée avec les symboles appropriés exportés.
- Les compilateurs GNU réussiront à compiler, avec un warning "warning: type attributes ignored after type is already defined [-Wattributes]" concernant template struct MYLIB_EXPORT foo<int>, puis si on link la librairie à un executable on aura des références indéfinies.

La solution pour les compilateurs GNU est de mettre MYLIB_EXPORT dans le extern template de header.hpp et non pas dans mylib.cpp (mais si on fait ça, c'est Visual Studio qui va échouer à compiler la librairie).
Enfin on peut mettre la macro dans les 2 fichiers, dans ce cas je pense que ça compile et link comme il faut, mais avec un tas de warnings bien dégueux.

Le problème, c'est que je ne trouve pas de manière élégante de le faire à la manière d'un generate_export_header. Par exemple il serait assez élégant d'avoir 2 macros automatiquement générées par CMake du type MYLIB_EXTERN_TEMPLATE (vide avec MSVC, égale à MYLIB_EXPORT pour les GNU) et MYLIB_TEMPLATE_INSTANTIATE (vide pour les GNU, égale à MYLIB_EXPORT pour MSVC).
Bien sur je pourrais le faire à la main dans un header qui inclut mylib_export.h, puis utiliser ce header à la place de mylib_export.h dans tous les fichiers qui l'utilisaient, mais se reposer sur CMake qui connait vachement mieux toutes les subtilités des compilateurs serait plus élégant à mon sens.

Quelqu'un aurait il une idée?