Home > Net >  How do I correctly reference a private Windows assembly in the Application Manifest?
How do I correctly reference a private Windows assembly in the Application Manifest?

Time:02-04

My setup and what I try to achieve

My project is set up to use CMake, Ninja as my generator and MSVC as my compiler. I have an executable target A.exe and 2 shared library targets (B.dll and C.dll). I'm on Windows and use load-time linking by linking to their static counterparts B.lib and C.lib. The dependency of this targets goes as follows: A.exe -> B.dll -> C.dll (read "->" as "depends on").

Everything compiles and builds successfully, but when I try run the program I get this error:

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

The basic folder structure of my project:

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

Code

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 files

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;
}

Manifests

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>

What I tried

  • As I read from the Microsoft Documentation, the C.manifest isn't actually necessary and all .dll files should be referenced in B.manifest, but that doesn't work either.
  • I tried to avoid using manifests, but if I do so, I get the same exact error.

What I wanted is to make my A.exe depend on B.dll which also depends on C.dll. I would like to know where I'm wrong and what can I do to achieve my goal.

CodePudding user response:

With the help of fellow programmers in the comments and a bit of adding and removing lines from .manifest files I finally made it work. Thanks to Simon Mourier

A should declare B and C dlls – Simon Mourier

What I was wrong about is declaring my B.dll and C.dll as separate private assemblies. What I had to do, in fact, is add the <file> tags to A.manifest as follows:

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

    <assemblyIdentity
            type="win32"
            name="A"
            language="cpp"
            processorArchitecture="amd64"
            version="1.0.0.0"
            />
    <!-- Added the .dll's to application manifest -->
    <file name="B.dll" />
    <file name="C.dll" />

</assembly>

Also, the B.manifest and C.manifest were no longer needed, and I excluded them from the build:

cmake_minimum_required(VERSION 3.22.0)
project(test VERSION 0.1.0)

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

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

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

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

With that, everything works just fine and outputs correct

  • Related