Generating a Visual Studio project including external MS projects

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:

  1. 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?

  2. 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?

Thanks,

Arlie Capps

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.

See code here and here.

Brad King wrote:

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>

Thanks,

Arlie

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.

Thanks very much for your help.