You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在应用程序清单中正确引用私有Windows程序集并解决并行配置错误

问题描述

我的环境与目标

项目使用CMake构建,Ninja作为生成器,MSVC作为编译器。包含一个可执行目标A.exe和两个共享库目标(B.dll和C.dll)。在Windows系统上通过链接对应的静态库B.lib和C.lib实现加载时链接,依赖关系:A.exe -> B.dll -> C.dll("->"表示依赖)。

项目编译构建成功,但运行程序时出现错误:

The Application has failed to start because its side to side configuration is incorrect

项目基础文件夹结构:

\
 | - A.cpp
 | - B.cpp
 | - C.cpp
 | - A.manifest
 | - B.manifest
 | - C.manifest
 | - CMakeLists.txt

代码

CMakeLists.txt:

cmake_minimum_required(VERSION 3.22.0)
project(test VERSION 0.1.0)

add_executable(
    A
    "A.cpp"
    "A.manifest"
)


add_library(
    B
    SHARED
    "B.cpp"
    "B.manifest"
)

add_library(
    C
    SHARED
    "C.cpp"
    "C.manifest"
)

target_link_libraries(B C) # B -> C
target_link_libraries(A B) # A -> B

CPP文件

A.cpp:

__declspec(dllimport) void B_test();

int main()
{
    B_test();
    return 0;
}

B.cpp:

__declspec(dllimport) void C_test();

__declspec(dllexport) void B_test()
{
    C_test();
}

C.cpp:

#include <iostream>

__declspec(dllexport) void C_test()
{
    std::cout << "Success" << std::endl;
}

清单文件

A.manifest:

<?xml version="1.0" encoding="UTF-8"?>
<assembly
        xmlns="urn:schemas-microsoft-com:asm.v1"
        manifestVersion="1.0"
        >

    <assemblyIdentity
            type="win32"
            name="A"
            language="*"
            processorArchitecture="amd64"
            version="1.0.0.0"
            />
            
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                    type="win32"
                    name="B"
                    language="*"
                    processorArchitecture="amd64"
                    version="1.0.0.0"
                    />
        </dependentAssembly>
    </dependency>

</assembly>

B.manifest:

<?xml version="1.0" encoding="UTF-8"?>
<assembly
        xmlns="urn:schemas-microsoft-com:asm.v1"
        manifestVersion="1.0"
        >

    <assemblyIdentity
            type="win32"
            name="B"
            language="*"
            processorArchitecture="amd64"
            version="1.0.0.0"
            />

    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                    type="win32"
                    name="C"
                    language="*"
                    processorArchitecture="amd64"
                    version="1.0.0.0"
                    />
        </dependentAssembly>
    </dependency>

    <file name="B.dll" />

</assembly>

C.manifest:

<?xml version="1.0" encoding="UTF-8"?>
<assembly
        xmlns="urn:schemas-microsoft-com:asm.v1"
        manifestVersion="1.0"
        >
    <!-- details about our side-by-side assembly-->
    <assemblyIdentity
            type="win32"
            name="C"
            language="*"
            processorArchitecture="amd64"
            version="1.0.0.0"
            />

    <file name="C.dll" />
</assembly>

已尝试方案

  • 根据微软文档,C.manifest并非必需,所有.dll应在B.manifest中引用,但此方法无效。
  • 尝试不使用清单文件,仍出现相同错误。

需求:实现A.exe依赖B.dll、B.dll依赖C.dll的正确配置,明确问题所在及解决方法。


解决方法

问题根源

  1. 手动清单与自动生成清单冲突:MSVC会自动生成包含CRT(C运行时库)依赖的清单文件,手动添加的清单会和自动生成的清单冲突,导致side-by-side配置错误。
  2. DLL部署路径问题:即使依赖关系正确,Windows无法找到B.dll和C.dll时,也会触发该错误。
  3. CMake处理清单的方式错误:直接将.manifest文件添加为目标源文件,会导致编译器错误地嵌入重复或不完整的清单信息。

具体修复步骤

1. 移除手动编写的清单文件,让MSVC自动生成

删除所有.manifest文件,同时修改CMakeLists.txt,移除对这些文件的引用:

cmake_minimum_required(VERSION 3.22.0)
project(test VERSION 0.1.0)

add_executable(
    A
    "A.cpp"
)

add_library(
    B
    SHARED
    "B.cpp"
)

add_library(
    C
    SHARED
    "C.cpp"
)

target_link_libraries(B C) # B -> C
target_link_libraries(A B) # A -> B

2. 确保所有输出文件在同一目录

CMake默认会将不同目标的输出放在不同子目录,需要统一输出目录,在CMakeLists.txt中添加以下配置:

# 设置所有目标的输出目录为同一位置
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# 针对多配置生成器(如MSVC),确保Debug/Release等目录下的输出也统一
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
    string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin/${OUTPUTCONFIG})
    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin/${OUTPUTCONFIG})
endforeach()

3. 确认MSVC运行时库配置

确保项目使用的运行时库一致,避免CRT依赖冲突,在CMakeLists.txt中添加:

# 设置MSVC运行时库为多线程DLL模式
if(MSVC)
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
endif()

4. 运行程序

重新构建项目后,A.exe、B.dll、C.dll会被输出到bin/Debug或bin/Release目录下,直接运行该目录下的A.exe即可。

自定义清单的正确姿势(如果确实需要)

如果必须使用自定义清单,不要直接将其添加为源文件,而是通过CMake的set_target_properties指定:

set_target_properties(A PROPERTIES LINK_FLAGS "/MANIFEST:NO") # 禁用自动生成的清单
set_target_properties(A PROPERTIES MANIFEST "${CMAKE_CURRENT_SOURCE_DIR}/A.manifest")

但这种方式需要确保自定义清单包含所有必要的依赖(包括CRT),否则仍会出现配置错误。


内容的提问来源于stack exchange,提问作者bub1ick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 07:45:29