Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake Generator for Visual Studio Linux cross-platform

I want to generate a Visual Studio Solution for a cross-platform Linux Project from a CMake Project.

The Visual Studio 2017 cross-platform workload works nicely, especially when it comes to debugging. I use it to target the WSL. Now I have an existing Linux CMake project that I want to develop on Windows and Visual Studio and build it on WSL. I just don't seem to see a way of generating an appropriate Solution for Visual Studio. Can anyone enlighten me?

like image 995
Felix Avatar asked Mar 13 '17 11:03

Felix


People also ask

Can Visual Studio generate CMake?

Visual Studio runs CMake and generates the CMake cache file ( CMakeCache. txt ) for the default configuration. The CMake command line is displayed in the Output Window, along with other output from CMake.

Does Linux use CMake?

The CMake Tools extension integrates Visual Studio Code and CMake to make it easy to configure, build, and debug your C++ project. In this tutorial, you'll use the CMake Tools extension for Visual Studio Code to configure, build, and debug a simple C++ CMake project on Linux.

How do I run a CMake project in Linux?

Running CMake from the command line From the command line, cmake can be run as an interactive question and answer session or as a non-interactive program. To run in interactive mode, just pass the option “-i” to cmake. This will cause cmake to ask you to enter a value for each value in the cache file for the project.

How do I run CMake in WSL?

Target Windows Subsystem for Linux To target WSL, select Manage Configurations in the configuration dropdown in the main toolbar: The CMakeSettings. json window appears. Press Add Configuration (the green '+' button) and then choose Linux-GCC-Debug or Linux-GCC-Release if using GCC.

Can I use CMake for cross platform development?

If you are using the same codebase for multiple targets, then CMake is the most common solution for building your software. You can use Visual Studio for your C++ cross platform development when using CMake without needing to create or generate Visual Studio projects. Just open the folder with your sources in Visual Studio (File > Open Folder ).

Can I generate a Visual Studio solution from a CMake project?

I want to generate a Visual Studio Solution for a cross-platform Linux Project from a CMake Project. The Visual Studio 2017 cross-platform workload works nicely, especially when it comes to debugging. I use it to target the WSL.

How to get started with CMake tools on Linux?

Get started with CMake Tools on Linux 1 Prerequisites #. Visual Studio Code. ... 2 Create a CMake project #. If you have an existing CMake project that already has a CMakeLists.txt file in the root directory, you can skip to Select a kit to ... 3 Configure Hello World #. ... 4 Build hello world #. ... 5 Debug hello world #. ...

How do I select a specific CMake generator for my project?

CMake Generators are platform-specific so each may be available only on certain platforms. The cmake (1) command-line tool --help output lists available generators on the current platform. Use its -G option to specify the generator for a new build tree. The cmake-gui (1) offers interactive selection of a generator when creating a new build tree.


1 Answers

There were already some queries to support the "Linux" project type by CMake, but I don't think that there is something implemented yet (looking at the code it's not able to generate the required project settings).

In those cases you can only work with include_external_msproject() command calls.

This would include an existing .vcproj file into your CMake generated solution like:

include_external_msproject(
    MyProject 
    ${CMAKE_CURRENT_SOURCE_DIR}/MyProject/MyProject.vcproj
)

So let's make a template of an existing Linux .vcxproj file like this:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="@[email protected]" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|x86">
      <Configuration>Debug</Configuration>
      <Platform>x86</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x86">
      <Configuration>Release</Configuration>
      <Platform>x86</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>@_guid@</ProjectGuid>
    <Keyword>Linux</Keyword>
    <RootNamespace>@_target@</RootNamespace>
    <MinimumVisualStudioVersion>@[email protected]</MinimumVisualStudioVersion>
    <ApplicationType>Linux</ApplicationType>
    <ApplicationTypeRevision>1.0</ApplicationTypeRevision>
    <TargetLinuxPlatform>Generic</TargetLinuxPlatform>
    <LinuxProjectType>{D51BCBC9-82E9-4017-911E-C93873C4EA2B}</LinuxProjectType>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
    <UseDebugLibraries>true</UseDebugLibraries>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
    <UseDebugLibraries>false</UseDebugLibraries>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings" />
  <ImportGroup Label="Shared" />
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros" />
  <ItemGroup>
    <ClCompile Include="@_sources@" />
  </ItemGroup>
  <ItemGroup>
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets" />
</Project>

And create a new add_linux_executable() command using this:

cmake_minimum_required(VERSION 2.8)

project(ConfigureVCXProjForLinux)

function(add_linux_executable _target)
    if (CMAKE_GENERATOR MATCHES "Visual Studio ([0-9]*)")
        foreach(_source IN LISTS ARGN)
            get_filename_component(_source_abs "${_source}" ABSOLUTE)
            file(TO_NATIVE_PATH "${_source_abs}" _source_native)
            list(APPEND _sources "${_source_native}")
        endforeach()
        file(TO_NATIVE_PATH "${CMAKE_CURRENT_LIST_FILE}" _list_file_native)
        list(APPEND _sources "${_list_file_native}")

        string(
            UUID _guid 
            NAMESPACE "2e4779e9-c831-47b0-b138-3745b2ed6ba9" 
            NAME ${_target}
            TYPE SHA1
            UPPER
        )

        configure_file(
           "LinuxTemplate.vcxproj.in" 
            "${CMAKE_CURRENT_BINARY_DIR}/${_target}.vcxproj" 
            @ONLY
        )

        include_external_msproject(
            ${_target}
            "${CMAKE_CURRENT_BINARY_DIR}/${_target}.vcxproj"
            TYPE "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"
            GUID "${_guid}"
        )
    endif()
endfunction()

file(WRITE "main.cpp" [=[
    #include <iostream>

    int main()
    {
        std::cout << "Hello Linux !" << std::endl;
    }
]=])
add_linux_executable(${PROJECT_NAME} "main.cpp")

Note the template replacements:

  • @CMAKE_MATCH_1@ for the Visual Studio version number
  • @_target@ for the project RootNamespace
  • @_sources@ for ever source file you have given ``add_linux_executable()` as an argument
  • @_guid@ a unique GUID for the project

This would still require one template per whatever compilation options you choose. But using templates makes this approach somewhat more flexible.

like image 125
Florian Avatar answered Sep 27 '22 23:09

Florian