代码之家  ›  专栏  ›  技术社区  ›  BleuGamer

在CMake中创建共享库时,如何检查或忽略丢失的DLL?

  •  0
  • BleuGamer  · 技术社区  · 6 年前

    问题:我想忽略'dll not found'错误并继续执行不依赖该库的代码。

    • 静态:编译时链接到可执行文件。
    • 模块:运行时加载的共享库,我还在理解中。

    我正在使用CMake'GenerateExportHeader'来简化我的共享库制作工作。这很管用。我甚至可以对这些库进行版本设置,以便在运行中进行更改。但是,我很难弄清楚的是,如果找不到dll,如何检查并可能忽略错误:

    “由于找不到xxx.dll,代码执行无法继续。重新安装程序可能会解决此问题。”

    我已经研究了“模块”类型的共享库,但我希望避免“\u declspec”和可加载库的混乱。

    所以。。。。代码:

    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)
    

    库.h:

    #pragma once
    
    namespace Library
    {
    
    class Library
    {
    public:
    
        void testing();
    
    };
    
    } // namespace Library
    

    #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放在那里,这就是我想做的。)
    • 手动'\u declspec'声明来手动执行此操作,这是可行的,但我希望(如果可能)避免这样做。有足够的信息让我能够把这些信息拼凑起来,我也愿意这么做,但我的想法是用类来编写代码,就像用可执行文件或库(用c++术语)来称为纯英语一样。

    最后一点才是我真正想要达到的。我希望能够编写c++代码,并使其对其他开发人员可读,而不必管理一些更复杂的功能,包括特定于平台的共享库加载。

    0 回复  |  直到 6 年前