Pull to refresh

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

Reading time8 min
Views36K
Ни для кого не секрет, что 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.
Tags:
Hubs:
Total votes 48: ↑44 and ↓4+40
Comments15

Articles

Information

Website
neobit.ru
Registered
Employees
51–100 employees
Location
Россия