I have a large program, configured with CMake, that links against several (tens of) libraries. The libraries are built with MS Visual Studio 2017 (using Intel C++ and Fortran compilers): they have handwritten project.vcxproj and .vfproj files.
CMake generates the MS Visual Studio solution, and I’m impressed with how far I’ve gotten. But I’m stuck on a linking problem and a nagging cosmetic issue.
Here is a (distilled) example of what I’m trying to do.
# liba is Fortran
include_external_msproject(liba
${CMAKE_SOURCE_DIR}/imports/liba/Win32/liba.vfproj
TYPE 6989167D-11E4-40FE-8C1A-2192A86A7E90
GUID 0000AAAA-BBBB-CCCC-87EE-000000FFFFFF)
# libb is C++ and needs liba
include_external_msproject(libb
${CMAKE_SOURCE_DIR}/imports/liba/Win32/libb.vcxproj
GUID 00CC00AA-BBB2-C3CC-87E1-00FF00FF00FF
liba)
set_property(TARGET liba PROPERTY FOLDER "Fortran Libraries")
set_property(TARGET libb PROPERTY FOLDER "C++ Libraries")
# prog_sources is defined earlier
add_executable(prog ${prog_sources})
add_dependencies(prog libb)
Questions:
The folder properties don’t work. When I opened the .sln file in Visual Studio, I hoped to see liba within the “Fortran Libraries” folder and libb inside the “C++ Libraries” folder, but there are no folders: all projects in the solution are at the top level. What am I doing wrong?
add_dependencies(prog libb) adds a ProjectReference to libb inside prog.vcxproj, as I expected, but prog tries to link to libb.lib. Several of my libraries’ output file names don’t match the project name, so I get a linker error complaining about “missing libb.lib”. Is there a way to set the file name that the linker should look for?
You’ll probably need to hack together an INTERFACE target here I think. It seems that include_external_msproject makes a utility (add_custom_target-like) target internally. There seems to be some magic internally about how these things get linked to (and I don’t see a specific .lib path from CMake; VS may be making that assumption somewhere), but I can’t decipher it right now. @brad.king?
When linking to a target loaded via include_external_msproject we depend on Visual Studio’s Link Library Dependencies feature. That’s supposed to link the proper .lib automatically.
When linking to a target loaded via include_external_msproject we
depend on Visual Studio’s Link Library Dependencies feature.
That’s supposed to link the proper .lib automatically.
(Links to code: cmGlobalVisualStudio8Generator.cxx#L324-342 and
cmVisualStudio10TargetGenerator.cxx#L3851-3855.)
Brad,
I see the generated project file does have the Link Library Dependencies property set to True: thanks for pointing that out. Additionally, though, the generated project file explicitly names libb.lib:
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> .... stuff .... </ClCompile>
.... more stuff ....
<Link>
<AdditionalDependencies>
.... lots of libraries;
libb.lib; .... <!-- where does this name come from? -->
</AdditionalDependencies>
.... yet more stuff ....
</Link>
</ItemDefinitionGroup>
the generated project file explicitly names libb.lib
We have a similar case in the test suite here and that does not happen. Please zip up a minimal source tree showing the problem and attach the example here.
the generated project file explicitly names libb.lib
We have a similar case in the test suite (link omitted) and that does not
happen. Please zip up a minimal source tree showing the problem and attach
the example here.
I’m having trouble making a minimal source tree. Additionally, I found some calls to target_link_libraries() that contributed at least some of the failures I’m finding, so I’ll continue to troubleshoot that way. I’ll send in a minimal reproducer if I can find one.