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 inB.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