Использование оболочки Visual Studio 2010 для компиляции проектов с помощью gcc в Linux

    Ни для кого не секрет, что Microsoft Visual Studio 2010 представляет собой мощную IDE, которая, помимо всего, позволяет заменять команды сборки проекта проектов путем внесения изменений в .vcxproj файлах. Как выяснилось, можно использовать эту возможность, чтобы заставить Visual Studio собирать проекты с помощью gcc, работающего на другом компьютере под управлением Linux. При этом обращение к gcc на Linux должно происходить по сети, например по ssh. В этой статье мы расскажем вам о проделанном нами эксперименте по такой необычной настройке Visual Studio.

    Предположим, у нас есть программа:


    #include <stdio.h>
    
    int main() 
    {
        printf("Hello world!");
        fflush(stdout);
        getchar();
        return 0;
    }
    


    Эта программа должна собираться в среде Linux и при помощи gcc. Конечно, это просто пример, на самом деле речь может идти о большом проекте для Linux с сотнями тысяч файлов и налаженной системой сборки на makefile, что не меняет сути предлагаемого решения. Наша задача – обеспечить возможность редактирования кода программы в Visual Studio и использования входящих в ее состав инструментов по анализу кода и других средств.
    Для начала сделаем простенький makefile для этой программы:

    NAME= test
    OBJS= main.o

    .SUFFIXES: .cpp
    .SUFFIXES: .o

    all: $(NAME)

    clean:
    rm -rf *.o

    cleanall: clean
    rm -rf *.d map dep *~ $(NAME)

    rebuild: cleanall all
    @eсho Rebuild done.

    $(NAME): $(OBJS)
    echo Compiling $(NAME).
    g++ -o $(NAME) $(OBJS)

    .cpp.o:
    gcc -c $*.cpp

    Теперь нужно решить следующую проблему: код должен редактироваться на платформе Windows (Visual Studio), а компилироваться в Linux. Для этого можно использовать виртуальные машины и разделяемыепапки. Например, в хостовой системе Windows можно установить любое средство виртуализации (Oracle VirtualBox или VMware Workstation), затем создать виртуальную машину и установить в ней Linux. В результате появляется возможность одновременно работать как с Windows, так и с Linux. Функция Shared Folders позволяет получить доступ к файлам хостовой ОС Windows из виртуальной машины Linux.
    Для VMware Workstation можно настроить shared folders, пробросив, например, D:\proj\ в Linux как папку proj. Тогда из Windows можно редактировать файл программы main.c, расположенный на диске Windows D:\proj\main.c и, при этом, компилировать его, используя gcc, в Linux в папке /mnt/hgfs/proj/.

    В Visual Studio можно заменить команды сборки проекта:
    • Build – сборка.
    • Rebuild – очистка и сборка проекта заново.
    • Clean – очистка файлов проекта (удаление всех бинарных файлов).
    плюс команда для запуска проекта.
    Для среды Linux они будут соответствовать следующим:
    • Build: make all
    • Rebuild: make rebuild
    • Clean: make clean
    • Запуск: ./test

    Наша задача — запускать в Windows так, будто бы они запускаются в обычном cmd, при этом ввод/вывод команд должен перенаправляться обратно в Windows, если мы хотим видеть ошибки компиляции прямо в среде из Visual Studio. Для решения этой задачи можно использовать утилитку plink.exe (скачивается на официальном сайте www.chiark.greenend.org.uk/~sgtatham/putty/download.html) из пакета Putty. Эта утилитка может выполнить одну команду по ssh, при этом корректно перенаправляя ввод/вывод на текущий терминал cmd.
    Допустим, Linux в виртуальной машине настроен так, что из Windows к нему можно обращаться по ssh используя IP адрес 192.168.1.8, имя пользователя — user, а пароль — 123456. Тогда, запустив cmd, можно в Windows успешно выполнить команду:
    D:\proj\tools>plink -batch -pw 123456 user@192.168.1.8 pwd
    /home/user
    Результат работы программы говорит нам о том, что ‘pwd’ выполнилось в домашнем каталоге пользователя user. Это значит, что прямо в cmd можно скомпилировать программку test следующим образом:

    D:\proj\tools>plink -batch -pw 123456 user@192.168.1.8 cd /mnt/hgfs/proj/; make rebuild
    rm -rf *.o
    rm -rf *.d map dep *~ test
    gcc -c main.cpp
    Compiling test.
    g++ -o test main.o
    Rebuild done.


    Теперь нам остается интегрировать указанный метод в Visual Studio. Для этого, создадим пустой Solution с названием vs_test в каталоге proj. Добавим проект ‘vs_test’ в созданный Solution. Проект должен иметь тип Makefile (все остальные настройки по умолчанию).







    В результате получится следующее дерево файлов:

    D:\proj\main.c
    D:\proj\makefile
    D:\proj\tools\plink.exe
    D:\proj\vs_test\vs_test.sln
    D:\proj\vs_test\vs_test.suo
    D:\proj\vs_test\vs_test.sdf
    D:\proj\vs_test\vs_test\vs_test.vcxproj
    D:\proj\vs_test\vs_test\vs_test.vcxproj.filters
    D:\proj\vs_test\vs_test\vs_test.vcxproj.user


    Далее нужно добавить в проект ‘vs_test’ наши makefile и main.c. Для этого следует воспользоваться опцией проекта ‘Add->Existing Item…’. Таким образом получим следующую картину в Solution Explorer:



    Далее, при помощи опции ‘Unload project’ выгружаем проект из solution.



    Теперь открываем на редактирование файл проекта при помощи опции ‘Edit vs_test.vcxproj’



    Теперь при помощи ‘File->New->File…’создаем текстовый файл, и называем его make_vs.props, размещая его в D:\proj\make_vs.props.
    Далее, при помощи тэга ‘Import’ включим текст файла make_vs.props в vs_test.vcxproj. Для этого в файле vs_test.vcxproj добавим строку, импортирующую дополнительные настройки проекта из make_vs.props:

    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
      <Import Project="$(SolutionDir)..\make_vs.props" />
      <ImportGroup Label="ExtensionSettings">
      </ImportGroup>


    В файле make_vs.props мы можем переопределить любые настройки проекта или дописать свои собственные. У нас получился такой файл make_vs.props:

    
    <?xml version="1.0" encoding="utf-8"?>
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
      <PropertyGroup Label="RemoteBuildLocals">
        <RblFolder>proj</RblFolder>
        <RblIncludePath>$(SolutionDir)\..\inc\</RblIncludePath>
        <RblExecute>./test</RblExecute>
      </PropertyGroup>
    
      <PropertyGroup Label="RemoteBuildSettings">
        <RbHost>192.168.1.8</RbHost>
        <RbUser>user</RbUser>
        <RbPassword>123456</RbPassword>
        <RbRoot>test_src</RbRoot>
      </PropertyGroup>
    
      <PropertyGroup Label="RemoteBuild">
        <RbToolArgs> -pw $(RbPassword) $(RbUser)%40$(RbHost) cd $(RbRoot); cd $(RblFolder);</RbToolArgs>
        <RbToolExe>$(SolutionDir)..\tools\plink -batch $(RbToolArgs)</RbToolExe>
        <RbBuildCmd>$(RbToolExe) make all</RbBuildCmd>
        <RbRebuildAllCmd>$(RbToolExe) make rebuild</RbRebuildAllCmd>
        <RbCleanCmd>$(RbToolExe) make cleanall</RbCleanCmd>
        <RbExecuteCmd>$(RbToolArgs) $(RblExecute)</RbExecuteCmd>
        <RbIncludePath>$(RblIncludePath)</RbIncludePath>
      </PropertyGroup>
    
      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
        <NMakeBuildCommandLine>$(RbBuildCmd)</NMakeBuildCommandLine>
        <NMakeReBuildCommandLine>$(RbRebuildAllCmd)</NMakeReBuildCommandLine>
        <NMakeCleanCommandLine>$(RbCleanCmd)</NMakeCleanCommandLine>
        <IncludePath>$(RbIncludePath)</IncludePath>
        <LocalDebuggerCommand>$(SolutionDir)..\tools\plink</LocalDebuggerCommand>
        <LocalDebuggerCommandArguments>$(RbExecuteCmd)</LocalDebuggerCommandArguments>
      </PropertyGroup>
    
      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
        <NMakeBuildCommandLine>$(RbBuildCmd)</NMakeBuildCommandLine>
        <NMakeReBuildCommandLine>$(RbRebuildAllCmd)</NMakeReBuildCommandLine>
        <NMakeCleanCommandLine>$(RbCleanCmd)</NMakeCleanCommandLine>
        <IncludePath>$(RbIncludePath)</IncludePath>
        <LocalDebuggerCommand>$(SolutionDir)..\tools\plink</LocalDebuggerCommand>
        <LocalDebuggerCommandArguments>$(RbExecuteCmd)</LocalDebuggerCommandArguments>
      </PropertyGroup>
    
    </Project>


    Перезагружаем проект при помощи ‘Reload project’. И просто нажимаем F5. Выглядеть все должно после этого следующим образом:




    Ура! Visual Studio для компиляции сама обратилась к make и gcc из Linux, и мы получили в окне IDE вывод от gcc и запустили нашу программу test, с которой так же можно работать из Windows.
    Теперь кратко разберем основной файл make_vs.props (начнем с конца..). Файл разбит на группы настроек, для того чтобы избежать лишнего копирования текста из одного проекта в другой (методика опробована на практике для Solution более чем из сотни проектов такого вида).
    Первый(на самом деле последний) блок — это блок настроек, которые Visual Studio использует для осуществления сборки проекта, состоит ихдвух дублирующихся групп для конфигураций Debug и Release.

    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
        <NMakeBuildCommandLine>$(RbBuildCmd)</NMakeBuildCommandLine>
        <NMakeReBuildCommandLine>$(RbRebuildAllCmd)</NMakeReBuildCommandLine>
        <NMakeCleanCommandLine>$(RbCleanCmd)</NMakeCleanCommandLine>
        <IncludePath>$(RbIncludePath)</IncludePath>
        <LocalDebuggerCommand>$(SolutionDir)..\tools\plink</LocalDebuggerCommand>
        <LocalDebuggerCommandArguments>$(RbExecuteCmd)</LocalDebuggerCommandArguments>
      </PropertyGroup>
    
      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
        <NMakeBuildCommandLine>$(RbBuildCmd)</NMakeBuildCommandLine>
        <NMakeReBuildCommandLine>$(RbRebuildAllCmd)</NMakeReBuildCommandLine>
        <NMakeCleanCommandLine>$(RbCleanCmd)</NMakeCleanCommandLine>
        <IncludePath>$(RbIncludePath)</IncludePath>
        <LocalDebuggerCommand>$(SolutionDir)..\tools\plink</LocalDebuggerCommand>
        <LocalDebuggerCommandArguments>$(RbExecuteCmd)</LocalDebuggerCommandArguments>
      </PropertyGroup>
    


    Как не трудно догадаться, значения тэгов следующие:
    • NMakeBuildCommandLine – команда Build (make all).
    • NMakeReBuildCommandLine – команда Rebuild (make rebuild).
    • NMakeCleanCommandLine – команда Clean (make clean).
    • IncludePath – список Include директорий. Без корректного списка VS не сможет нормально обработать и распарсить Ваш код.
    • LocalDebuggerCommand – команда запуска программы после компиляции.
    • LocalDebuggerCommandArguments – аргументы команды при запуске программы после компилляции.

    На данном этапе все значения указаны ссылками для других настроек. Эту группу настроек удобно выделить в Common.props и включать всегда во все проекты такого вида.

    Следующая группа настроек соответствует заданию команд, которые должны выполняться при сборке.
    .
     <PropertyGroup Label="RemoteBuild">
        <RbToolArgs> -pw $(RbPassword) $(RbUser)%40$(RbHost) cd $(RbRoot); cd $(RblFolder);</RbToolArgs>
        <RbToolExe>$(SolutionDir)..\tools\plink -batch $(RbToolArgs)</RbToolExe>
        <RbBuildCmd>$(RbToolExe) make all</RbBuildCmd>
        <RbRebuildAllCmd>$(RbToolExe) make rebuild</RbRebuildAllCmd>
        <RbCleanCmd>$(RbToolExe) make cleanall</RbCleanCmd>
        <RbExecuteCmd>$(RbToolArgs) $(RblExecute)</RbExecuteCmd>
        <RbIncludePath>$(RblIncludePath)</RbIncludePath>
      </PropertyGroup> 
    

    Значения тэгов следующие:
    • RbToolArgs – стандартные аргументы утилиты plink которые будут использоваться всегда.
    • RbToolExe – общее значение начала всех команд, которые будут использоваться далее.
    • RbBuildCmd – простая команда Build.
    • RbRebuildAllCmd – простая команда Rebuild.
    • RbCleanCmd – простая команда Clean.
    • RbExecuteCmd – для запуска программы test после сборки все делится на команду и аргументы – эта часть отвечает за аргументы.
    • RbIncludePath – переобозначенный список Include директорий.

    Описанную группу настроек удобно выделить в тот же Common.props.

    Следующая группа настроек, общая для всех проектов, но некоторые параметры будут различаться в зависимости от настроек стенда.

     <PropertyGroup Label="RemoteBuildSettings">
        <RbHost>192.168.1.8</RbHost>
        <RbUser>user</RbUser>
        <RbPassword>123456</RbPassword>
        <RbRoot>test_src</RbRoot>
      </PropertyGroup> 


    Как можно видеть, указаны имя хоста, идентификатор пользователя и его пароль, а так же путь к каталогу с файлами проектов для Linux. Эти настройки удобно выделить в специальный user.props и включать его в Common.props при помощи тэга Import.
    Последняя группа настроек касается только конкретного проекта.

     <PropertyGroup Label="RemoteBuildLocals">
        <RblFolder>proj</RblFolder>
        <RblIncludePath>$(SolutionDir)\..\inc\</RblIncludePath>
        <RblExecute>./test</RblExecute>
      </PropertyGroup>


    Значения тэгов следующие:
    • RblFolder – папка, где находятся файлы проекта (для Linux).
    • RblIncludePath – список Include директорий (для Windows).
    • RblExecute – команда для запуска.



    Учтите, что при каждой команде Build происходит установка ssh соединения, что требует некоторого времени (например, у меня выходило порядка 2-5 секунд).
    В итоге у нас получилось заставить Visual Studio оcуществлять сборку проекта при помощи makefile и gcc из Linux.
    НеоБИТ
    68,00
    Компания
    Поделиться публикацией

    Комментарии 15

      +3
      Просто для информации, есть еще такая платная вещь как Visual GDB упрощающая настройки и отладку GCC проектов под Visual Studio visualgdb.com/
        +4
        Я восхищаюсь такими программными инженерами, кто бы они ни были.
          0
          в своё время я пользовался bvrde которая is a fully integrated development environment (IDE) for remote cross-platform compiling and debugging of UNIX and LINUX
            +2
            Смотрел в своё время MagicUnix — делал то же самое. Но за идею с VS — брависсимо!
              0
              > Так или иначе, были продемонстрированы возможности Visual Studio по настройке системы сборки проектов.

              Лабораторку недавно писали небось?
                –1
                вот и я думаю, а нафига оно все надо было? не, конечно круто, расковыряли, настроили, запустили — молодцы! но практическая польза какая?
                  +2
                  не, я не о том, что нафига. Оно интересно вышло. Просто стиль очень напомнил «таким образом, в данной лабораторной работе мы узнали...»
                0
                Ребята, вы очень круты!
                  +1
                  Если ваша программа не кроссплатформенная, то как будут работать фичи в Visual Studio? Она ведь не сможет понять вашу программу.
                    0
                    Спасибо! Есть конечно платные visualgdb и wingdb, но поскольку они платные, то механизм их работы и исходники аддинов были недоступны.
                      +5
                      Ура! Visual Studio сама обратилась к Linux, который скомпилировал проект, и мы получили в окне IDE все что напечатал gcc; в итоге мы запустили нашу программу test с которой так же можно работать из Windows.

                      Я что-то не очень понял, почему Ура? На скриншоте во-первых вижу ошибку компиляции, а во-вторых у студии видно что автокомплит не работает, т.е. по сути бесполезная какая-та интеграция получается (особенно учитывая что и отладчик не будет работать).

                      Ну, а в саму вижу достаточно просто любую команду сборки прописать. В свойствах проекта указываем makefile и жмем применить:

                      Затем идем на вкладочку nmake и пишем в build command line, clean, rebuild нужные нам команды которые могут вызывать все что угодно, ну а в output путь до нашего бинарника, который собирается и который можно будет запустить под отладчиком (если отладочная сборка).

                      В моем примере как видно на скриншоте я просто задал свой mingw компилятор в качестве команды сборки.

                      Но толку особого от этого не будет если компилятор не студийный используется при сборке, т.к. даже на ошибку в консоли нельзя перейти, т.к. MSVC умеет парсить только аутпут от своего компилятора. В Eclipse, например, это реализовано с помощью плагинов и там нормально парсится любой компилятор, достаточно в конфигурации установить галочку напротив нужного.
                        0
                        если запускать хитронавороченную команду, то можно и выхлоп переформатировать так, чтобы студия на нужные строчки переходила.
                        +1
                        Практически везде в тексте вместо «Visual Studio» следует читать «MSBuild».
                          +1
                          Мы используем для удаленной компиляции NetBeans. Хоть он с багами и тормозит, но зато пытается подтягивать инклуды и выполнять автокомплит.
                            0
                            Можно студии путь до hников указать и радоваться автокомплиту

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое