0

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.

bub1ick
  • 21
  • 6
  • Usually I see stuff like this when the installed Visual Studio runtime libraries aren't quite right. – user4581301 Feb 01 '23 at 21:00
  • 1
    Can you please read about [the problems with images of text](//meta.stackoverflow.com/a/285557/11107541) and then [edit] to **add a transcription** of your images of the error message as actual text? Perhaps useful: [/help/formatting](/help/formatting). – starball Feb 01 '23 at 22:17
  • Related: https://answers.microsoft.com/en-us/windows/forum/all/the-application-has-failed-to-start-because-its/634458e4-e02f-4bdc-aab8-c148a9a3f61a – starball Feb 01 '23 at 22:19
  • 1
    You can look at the Windows Event Viewer, it usually adds information to SxS errors. Also I kinda remember (not 100% sure) that you only need to declare dependencies in .exe manifest, not in each dll. So you should put B and C deps in A and remove deps from B. – Simon Mourier Feb 02 '23 at 06:43
  • 1
    Here's a tip: You can press [CTRL]+C for any standard message box (like the error dialog) and have it copy a textual representation of the dialog into the clipboard. As for diagnosing the issue, you can enable [loader snaps](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/show-loader-snaps) and run the application with a debugger attached. The [fuslogvw.exe](https://learn.microsoft.com/en-us/dotnet/framework/tools/fuslogvw-exe-assembly-binding-log-viewer) might be useful, too. – IInspectable Feb 02 '23 at 08:29
  • @IInspectable, Thanks for the useful tip I'll checkout your advice i bit later and try to debug it. – bub1ick Feb 02 '23 at 09:50
  • @SimonMourier, I'll check the Event Viewer for any hints to resolving the error. I'll try to reference the .dll's in the application file as well and see if that works. – bub1ick Feb 02 '23 at 09:51
  • @SimonMourier, the Event Viewer tells me that Windows can't find the `B.dll` assembly, though the `` tags are equal. Removing the "`B.dll` -> `C.dll`" dependency didn't help as the problem is with the `A.exe`'s manifest as far as I can understand. – bub1ick Feb 02 '23 at 11:09
  • A should declare B and C dlls – Simon Mourier Feb 02 '23 at 11:15
  • @IInspectable, I enabled the loader snaps through `gflags.exe` and fired up the WinDbg. There I clicked `File`->`Open Executable...` and chose my debug build of `A.exe`. When I clicked `OK` I was presented with basically the same exact error, but just in a different dialog. For now I can't paste the error message here, because the machine I'm working on right now isn't using English and I can't change it, but I will add this to the question body in a couple of hours' time. What other steps can I do to solve the issue? – bub1ick Feb 02 '23 at 11:27
  • @SimonMourier, in the `` section of Applicaiton Manifest? – bub1ick Feb 02 '23 at 11:28
  • @SimonMourier, I did in fact added the `` tags with the `B.dll` and `C.dll`. I also tried to add them to the Application manifest but it doesn't work either. – bub1ick Feb 02 '23 at 11:34
  • Loader snaps print information to the attached debugger's output log. As an aside, this doesn't require debug symbols. You can attach to a release configuration just as well. – IInspectable Feb 02 '23 at 11:36
  • @IInspectable, could you please explain how can I save or view this log, or give the link explaining it? I couldn't find it in the web. – bub1ick Feb 02 '23 at 11:41
  • I think I've managed to make it work! I'll post the solution! Thanks IInspectable and SimonMourier for your help a lot! – bub1ick Feb 02 '23 at 12:17

1 Answers1

0

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

bub1ick
  • 21
  • 6