Краткий ответ
Вы можете сделать это с помощью новой версии CMake (любая версия cmake-3.3.20150721-g9cd2f-win32-x86.exe или выше).
В настоящее время он находится в ветке dev.
Позже эта функция будет добавлена в релизную версию cmake-3.4.
Ссылка на cmake dev:
cmake_dev
Ссылка на статью, описывающую технику:
Создание библиотек Windows без declspec () с использованием новой функции экспорта всех CMake
Ссылка на пример проекта:
cmake_windows_export_all_symbols
Длинный ответ
Внимание:
Вся информация ниже относится к компилятору MSVC или Visual Studio.
Если вы используете другие компиляторы, такие как gcc в Linux или MinGW gcc-компилятор в Windows, у вас не будет ошибок компоновки из-за неэкспортированных символов, поскольку компилятор gcc по умолчанию экспортирует все символы в динамическую библиотеку (dll) вместо MSVC или Windows-компиляторы Intel.
В Windows вы должны явно экспортировать символ из DLL.
Более подробную информацию об этом можно получить по ссылкам:
Экспорт из DLL
HowTo: экспорт классов C ++ из DLL
Итак, если вы хотите экспортировать все символы из dll с помощью MSVC (компилятор Visual Studio), у вас есть два варианта:
- Используйте ключевое слово __declspec (dllexport) в определении класса / функции.
- Создайте файл определения модуля (.def) и используйте файл .def при сборке DLL.
1. Используйте ключевое слово __declspec (dllexport) в определении класса / функции
1,1. Добавьте макросы «__declspec (dllexport) / __declspec (dllimport)» к классу или методу, который вы хотите использовать. Поэтому, если вы хотите экспортировать все классы, вы должны добавить эти макросы ко всем из них
Более подробную информацию об этом можно получить по ссылке:
Экспорт из DLL с использованием __declspec (dllexport)
Пример использования (заменить «Проект» на реальное название проекта):
// ProjectExport.h
#ifndef __PROJECT_EXPORT_H
#define __PROJECT_EXPORT_H
#ifdef USEPROJECTLIBRARY
#ifdef PROJECTLIBRARY_EXPORTS
#define PROJECTAPI __declspec(dllexport)
#else
#define PROJECTAPI __declspec(dllimport)
#endif
#else
#define PROJECTAPI
#endif
#endif
Затем добавьте "PROJECTAPI" ко всем классам.
Определите «USEPROJECTLIBRARY» только если вы хотите экспортировать / импортировать символы из dll.
Определите "PROJECTLIBRARY_EXPORTS" для DLL.
Пример экспорта класса:
#include "ProjectExport.h"
namespace hello {
class PROJECTAPI Hello {}
}
Пример экспорта функции:
#include "ProjectExport.h"
PROJECTAPI void HelloWorld();
Внимание: не забудьте включить файл "ProjectExport.h".
1,2. Экспорт в функции C.
Если вы используете компилятор C ++ для написания кода компиляции на C, вы можете добавить extern "C" перед функцией, чтобы исключить искажение имени
Более подробную информацию об искажении имен в C ++ можно получить по ссылке:
Название Украшение
Пример использования:
extern "C" __declspec(dllexport) void HelloWorld();
Более подробную информацию об этом можно получить по ссылке:
Экспорт функций C ++ для использования в исполняемых файлах языка C
2. Создайте файл определения модуля (.def) и используйте файл .def при сборке DLL
Более подробную информацию об этом можно получить по ссылке:
Экспорт из DLL с использованием файлов DEF
Далее я опишу три подхода к созданию файла .def.
2,1. Функции экспорта C
В этом случае вы можете просто добавить объявления функций в файл .def вручную.
Пример использования:
extern "C" void HelloWorld();
Пример файла .def (соглашение об именах __cdecl):
EXPORTS
_HelloWorld
2,2. Экспорт символов из статической библиотеки
Я попробовал подход, предложенный "user72260".
Он сказал:
- Во-первых, вы можете создать статическую библиотеку.
- Затем используйте «dumpbin / LINKERMEMBER» для экспорта всех символов из статической библиотеки.
- Разобрать вывод.
- Поместить все результаты в файл .def.
- Создать dll с файлом .def.
Я использовал этот подход, но не всегда удобно создавать две сборки (одну как статическую, а другую как динамическую библиотеку). Однако я должен признать, что этот подход действительно работает.
2,3. Экспорт символов из файлов .obj или с помощью CMake
2.3.1. С использованием CMake
Важное замечание: Вам не нужны макросы экспорта в классы или функции!
Важное замечание: Вы не можете использовать / GL ( Оптимизация всей программы ) при использовании этого подхода!
- Создать проект CMake на основе файла "CMakeLists.txt".
- Добавьте следующую строку в файл «CMakeLists.txt»:
установлено (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
- Затем создайте проект Visual Studio с помощью «CMake (cmake-gui)».
- Скомпилируйте проект.
Пример использования:
Корневая папка
CMakeLists.txt (корневая папка)
cmake_minimum_required(VERSION 2.6)
project(cmake_export_all)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(dir ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${dir}/bin")
set(SOURCE_EXE main.cpp)
include_directories(foo)
add_executable(main ${SOURCE_EXE})
add_subdirectory(foo)
target_link_libraries(main foo)
main.cpp (корневая папка)
#include "foo.h"
int main() {
HelloWorld();
return 0;
}
Папка Foo (корневая папка / папка Foo)
CMakeLists.txt (папка Foo)
project(foo)
set(SOURCE_LIB foo.cpp)
add_library(foo SHARED ${SOURCE_LIB})
foo.h (папка Foo)
void HelloWorld();
foo.cpp (папка Foo)
#include <iostream>
void HelloWorld() {
std::cout << "Hello World!" << std::endl;
}
Снова ссылка на пример проекта:
cmake_windows_export_all_symbols
CMake использует подход, отличный от подхода «2.2. Экспорт символов из статической библиотеки».
Это делает следующее:
1) Создайте файл "objects.txt" в каталоге сборки с информацией о том, что файлы .obj используются в dll.
2) Скомпилируйте dll, то есть создайте .obj файлы.
3) На основе информации файла "objects.txt" извлечь все символы из файла .obj.
Пример использования:
DUMPBIN /SYMBOLS example.obj > log.txt
Подробнее об этом можно узнать по ссылке:
/ СИМВОЛЫ
4) Извлечь из файла .obj информацию.
По моему мнению, я бы использовал конвекцию вызова, например, поле «__cdecl / __ fastcall», «SECTx / UNDEF» (третий столбец), поле «External / Static» (пятый столбец), «??» "?" информация для анализа файлов .obj.
Я не знаю, как именно CMake анализирует файл .obj.
Тем не менее, CMake является открытым исходным кодом, так что вы можете узнать, заинтересован ли он для вас.
Ссылка на проект CMake:
CMake_github
5) Поместить все экспортированные символы в файл .def.
6) Связать DLL с использованием файла .def.
Шаги 4) -5), то есть анализ файлов .obj и создание файла .def перед компоновкой и использованием файла .def, который CMake делает с помощью «события Pre-Link».
Пока срабатывает «событие Pre-Link», вы можете вызывать любую программу, какую захотите.
Поэтому в случае «использования CMake» «Событие Pre-Link» вызовите CMake со следующей информацией о том, куда поместить файл .def и где находится файл «objects.txt» и с аргументом «-E __create_def».
Вы можете проверить эту информацию, создав проект CMake Visusal Studio с параметром «set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)», а затем проверьте файл проекта «.vcxproj» для dll.
Если вы попытаетесь скомпилировать проект без «set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)» или с «set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF)», вы получите ошибки компоновки из-за того, что символы не экспортируются из dll. * 1252
Более подробную информацию об этом можно получить по ссылке:
Понимание пользовательских шагов сборки и событий сборки
2.3.2. Без использования CMake
Вы можете самостоятельно создать небольшую программу для анализа файла .obj без использования CMake. Однако я должен признать, что CMake - очень полезная программа, особенно для кроссплатформенной разработки.