conan icon indicating copy to clipboard operation
conan copied to clipboard

[bug] MSBuildDeps is adding .lib extension to libraries regardless of linker

Open arnaudmathias opened this issue 8 months ago • 6 comments

Describe the bug

conan 2.16.1 Windows 11

Description: The MSBuildDeps generator is adding the .lib extension to libraries regardless of the actual linker in use. As MSBuild support Android/Linux workflows, the generated .props are not usable for cross-platform development.

For example with Android Arm64:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="ConanVariables">
    ...
    <Conanfmt__fmtLibraries>fmt.lib;</Conanfmt__fmtLibraries>
    ...
  </PropertyGroup>
</Project>

Expected behavior: Only add the .lib extension when the linker require it (msvc link.exe, clang-cl link.exe?)

I investigated a bit on my side and it seems like this part of the code is at fault. As the libraries name don't have an extension at this point, the else case is always triggered but I'm unsure of the best way to fix it (is there a way to get the linker, do we even know what linker will be used?)

How to reproduce it

It can be reproduced by using the MSBuildDeps generator with a profile that is targeting another platform than Windows. For example with an Android profile:

Android Profile

[settings]
os=Android
os.api_level=21
arch=armv8
compiler=clang
compiler.version=12
compiler.libcxx=c++_shared
compiler.cppstd=17

[tool_requires]
android-ndk/[*]

conanfile.py

from conan import ConanFile

class Recipe(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "MSBuildDeps"

    def layout(self):
        self.folders.generators = "conan"

    def requirements(self):
        self.requires("fmt/10.2.1")

install with the provided profile conan install conanfile.py -s build_type=Release --profile android.profile

Then checking the generated props for the library name in conan/conan_fmt__fmt_vars_release_arm64.props, we can see the extension is wrong <Conanfmt__fmtLibraries>fmt.lib;</Conanfmt__fmtLibraries>

arnaudmathias avatar May 02 '25 09:05 arnaudmathias

Only add the .lib extension when the linker require it (msvc link.exe, clang-cl link.exe?)

Link.exe requires a filename (with the extension), but it does not care about what the extension is (doesn't have to be .lib).

I suspect we have not really considered MSBuildDeps being used for anything other than Windows+msvc.

Are there documented instructions on how to use Visual Studio/C++ with the Android NDK, so that we can have a look?

jcar87 avatar May 02 '25 10:05 jcar87

Are there documented instructions on how to use Visual Studio/C++ with the Android NDK, so that we can have a look?

Android Install cross-platform mobile development with C++ This is a good starting point on how to configure Visual Studio for Android

Build an app for Android, iOS, and Windows (C++) You can then create a android C++ library to test thing out

Linux Download, install, and set up the Linux workload For Linux, it involve setting up an ssh connection to the local WSL installation or to a remote linux box

arnaudmathias avatar May 02 '25 14:05 arnaudmathias

Excellent, thanks @arnaudmathias ! The Visual Studio instructions is exactly what we needed - we'll try to reproduce this and make sure that this works.

@memsharded - I suspect the location deduction of the newer CMakeConfigDeps/BazelDeps may come in handy here

jcar87 avatar May 02 '25 14:05 jcar87

I'll have a look at this, it seems the full location isn't even really necessary, just making sure the extension is correct.

memsharded avatar May 02 '25 16:05 memsharded

I can confirm that the MSBuild integrations (MSBuildToolchain, MSBuildDeps) are not prepared to cross-build to Android.

My first steps have failed in MSBuildToolchain, with the conan new msbuild_exe template are failing:

  • That template defines a regular Windows console app
  • It doesn't generate the conanvcvars to enable the VS tools.
  • If I try to bypass the os=Android, then it keeps not generating the conanvcvars, because the profile is missing
    compiler.runtime=dynamic
    compiler.runtime_version=v144
    
    It is not very clear to me what should be the configuration for this cross-building, it seems these runtime settings are not really necessary for Android builds, and are only valid for LLVM/Clang for Windows.
  • Then the generated Platform defined fails The specified solution configuration "Release|ARM64" is invalid. What would be the configuration of

Then, forgetting about MSBuildToolchain, and trying to use only MSBuildDeps:

  • I have tried to change the <ConanmylibLibraries>mylib;</ConanmylibLibraries> to include all combinations: libmylib.a, libmylib, mylib, mylib.a, and the library is never found
  • I have checked in the cache folder, the library built was libmylib.a, and it exists there.

I am not sure why the library is not found.

I built the dependency with a CMake package which is relatively easy to build following the tutorial in https://docs.conan.io/2/examples/cross_build/android/ndk.html, from conan new cmake_lib template. How did you built your dependency, also with CMake?

memsharded avatar May 02 '25 18:05 memsharded

I have never used MSBuildToolchain but I forgot to mention that the fact that to make it work, I had to manually inject the NDK coming from conan in my projects

<PropertyGroup>
  <VS_NdkRoot>$(Conanandroid-ndk_buildRootFolder)/bin</VS_NdkRoot>
</PropertyGroup>

This variable seems to be poorly documented online but I picked it up from Android.Common.props in the Visual Installation folder

How did you built your dependency, also with CMake?

Yes, the dependency was built with CMake. I just used fmt from conancenter on my side

arnaudmathias avatar May 03 '25 05:05 arnaudmathias