ПРОБЛЕМА. Я хотел бы игнорировать ошибки 'dll not found' и продолжить выполнение кода, который не зависит от этой библиотеки.
Я понимаю, что это требует много, но нет никакого определенного руководства по общим библиотекам, и беспорядок в разговорах там запутывает. Я понял, что есть три типа библиотек, о которых знает CMake:
- Статический: связан с исполняемым файлом при компиляции.
- Shared: UNIX: загружается всякий раз, когда WINDOWS: требует, чтобы при компиляции компоновалась библиотека STATIC символов, которая отображает DLL.
- Модуль: динамически загружаемая разделяемая библиотека, о которой я все еще разбираюсь.
Я использую CMake 'GenerateExportHeader', чтобы упростить мою жизнь при создании общих библиотек. Это работает. Я даже могу сделать версию этих библиотек, чтобы изменить их на лету. Однако я не могу понять, как проверить и, возможно, игнорировать ошибку, если dll не найдена:
"Выполнение кода не может быть продолжено, поскольку xxx.dll не был найден. Повторная установка программы может решить эту проблему."
Я попытался поместить блоки try / catch в создание объекта include /. Google foo ничего не нашел.
Я заглянул в разделяемую библиотеку типа "MODULE", но я надеялся избежать путаницы с __declspec и загружаемых библиотек.
CMake 'GenerateExportHeader' очень и очень хорош, и если то, что я запрашиваю, невозможно без ручного экспорта символов, это хорошо, но я подумал, что могу спросить у гуру.
Итак .... Код:
CMakeLists.txt:
...
set(BUILD_SHARED_LIBS ON)
set(BUILD_TYPE SHARED)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
include(GenerateExportHeader)
...
# Create the library.
add_library(${NAME} ${BUILD_TYPE}
${SOURCES}
)
# Visual Studio Source Tree and filters.
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})
set_property(TARGET ${NAME} PROPERTY FOLDER "${NAME}")
if(BUILD_SHARED_LIBS)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
GENERATE_EXPORT_HEADER(${NAME}
BASE_NAME ${NAME}
EXPORT_MACRO_NAME ${NAME}_EXPORTS
EXPORT_FILE_NAME ${NAME}_EXPORTS.h
STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC)
endif(BUILD_SHARED_LIBS)
target_include_directories(${NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public>
$<INSTALL_INTERFACE:public>
PRIVATE private
)
# Link to other libraries.
target_link_libraries(${NAME}
${EXAMPLE_LIBRARY}
)
# 'make install' to correct locations.
install(TARGETS ${NAME} EXPORT ${NAME}Config
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin) # For windows.
install(DIRECTORY public/ DESTINATION include)
# 'public'/ project, 'include' for install.
# Importable from the install directory.
# Configs in per-project dir.
install (EXPORT ${NAME}Config DESTINATION share/${NAME}/cmake)
# Importable from the build directory.
export(TARGETS ${NAME} FILE ${NAME}Config.cmake)
# Library Testing/Future unit tests.
set(TESTING_PRIVATE
Tests/Main.cpp
)
set(TESTING_PUBLIC
)
set(TESTING_COLLECTIVE
${TESTING_PRIVATE}
${TESTING_PUBLIC}
)
add_executable(${NAME}Develop
${TESTING_COLLECTIVE}
)
set_property(TARGET ${NAME}Develop PROPERTY FOLDER "${NAME}")
target_include_directories(${NAME}Develop
PUBLIC ${CMAKE_BINARY_DIR}/exports
)
if(NOT BUILD_MODULAR_LIBS)
target_link_libraries(${NAME}Develop
${NAME}
)
endif(NOT BUILD_MODULAR_LIBS)
В моем коде нет ничего конкретного, поэтому для целей этого вопроса я упростил тестовый пример.
library.h:
#pragma once
namespace Library
{
class Library
{
public:
void testing();
};
} // namespace Library
Library.cpp:
#include <iostream>
#include "Library.h"
namespace Library
{
void Library::testing()
{
std::cout << "Library API: Hello, world!.... VERSIONED!" << std::endl;
}
} // namespace Library
Тест / main.cpp:
#include <iostream>
#include <conio.h>
// Tried different error handling, I think I need preprocessors here for this... google didn't help.
// I feel that I should be referencing the DLL, not the header
// and I couldn't find information in wikis or CMake documentation.
#include "Library.h"
int main(int argc, char const *argv[])
{
// The same applies for these two lines.
Library::Library test;
test.testing();
std::cout << "Press any key to exit..." << std::endl;
_getch();
return 0;
}
ЧТО Я ПОПРОБОВАЛ:
- Размещение блоков try / catch вокруг кода, который ссылается на библиотеку. РЕДАКТИРОВАТЬ: Да, я знаю, что это плохо и, вероятно, никогда не будет работать, но я не знал, может ли что-то внутреннее вызывать загрузку библиотеки.
- Компиляция версии моей программы с и без библиотек опций. (Честно говоря ... это плохо ... очень плохо ... директивы препроцессора могут решить эту проблему, но это означает, что каждый человек, если они хотят иметь адаптированную версию без определенных библиотек, должен был бы создавать себя, а не просто отбрасывать dll, который они ' я бы хотел там, что я и хотел бы сделать.)
- Ручные объявления '__declspec', чтобы сделать это вручную, что работает, но я бы хотел (если это возможно) избегать. Существует достаточно информации, которую я смог собрать вместе, и я готов это сделать, но на самом деле идея состоит в том, чтобы написать код с классами WITH точно так же, как исполняемый файл или библиотека, в которой (в терминах c ++) можно было бы назвать простой английский .
Этот последний пункт - действительно то, чего я пытаюсь достичь. Я хотел бы иметь возможность писать код на С ++ и делать его читаемым для других разработчиков без необходимости управлять некоторыми более сложными функциями, включая загрузку общей библиотеки для конкретной платформы.