Ни для кого не секрет, что Microsoft Visual Studio 2010 представляет собой мощную IDE, которая, помимо всего, позволяет заменять команды сборки проекта проектов путем внесения изменений в .vcxproj файлах. Как выяснилось, можно использовать эту возможность, чтобы заставить Visual Studio собирать проекты с помощью gcc, работающего на другом компьютере под управлением Linux. При этом обращение к gcc на Linux должно происходить по сети, например по ssh. В этой статье мы расскажем вам о проделанном нами эксперименте по такой необычной настройке Visual Studio.
Предположим, у нас есть программа:
Эта программа должна собираться в среде 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 следующим образом:
Теперь нам остается интегрировать указанный метод в 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:
В файле make_vs.props мы можем переопределить любые настройки проекта или дописать свои собственные. У нас получился такой файл make_vs.props:
Перезагружаем проект при помощи ‘Reload project’. И просто нажимаем F5. Выглядеть все должно после этого следующим образом:
Ура! Visual Studio для компиляции сама обратилась к make и gcc из Linux, и мы получили в окне IDE вывод от gcc и запустили нашу программу test, с которой так же можно работать из Windows.
Теперь кратко разберем основной файл make_vs.props (начнем с конца..). Файл разбит на группы настроек, для того чтобы избежать лишнего копирования текста из одного проекта в другой (методика опробована на практике для Solution более чем из сотни проектов такого вида).
Первый(на самом деле последний) блок — это блок настроек, которые Visual Studio использует для осуществления сборки проекта, состоит ихдвух дублирующихся групп для конфигураций Debug и Release.
Как не трудно догадаться, значения тэгов следующие:
• NMakeBuildCommandLine – команда Build (make all).
• NMakeReBuildCommandLine – команда Rebuild (make rebuild).
• NMakeCleanCommandLine – команда Clean (make clean).
• IncludePath – список Include директорий. Без корректного списка VS не сможет нормально обработать и распарсить Ваш код.
• LocalDebuggerCommand – команда запуска программы после компиляции.
• LocalDebuggerCommandArguments – аргументы команды при запуске программы после компилляции.
На данном этапе все значения указаны ссылками для других настроек. Эту группу настроек удобно выделить в Common.props и включать всегда во все проекты такого вида.
Следующая группа настроек соответствует заданию команд, которые должны выполняться при сборке.
.
Значения тэгов следующие:
• RbToolArgs – стандартные аргументы утилиты plink которые будут использоваться всегда.
• RbToolExe – общее значение начала всех команд, которые будут использоваться далее.
• RbBuildCmd – простая команда Build.
• RbRebuildAllCmd – простая команда Rebuild.
• RbCleanCmd – простая команда Clean.
• RbExecuteCmd – для запуска программы test после сборки все делится на команду и аргументы – эта часть отвечает за аргументы.
• RbIncludePath – переобозначенный список Include директорий.
Описанную группу настроек удобно выделить в тот же Common.props.
Следующая группа настроек, общая для всех проектов, но некоторые параметры будут различаться в зависимости от настроек стенда.
Как можно видеть, указаны имя хоста, идентификатор пользователя и его пароль, а так же путь к каталогу с файлами проектов для Linux. Эти настройки удобно выделить в специальный user.props и включать его в Common.props при помощи тэга Import.
Последняя группа настроек касается только конкретного проекта.
Значения тэгов следующие:
• RblFolder – папка, где находятся файлы проекта (для Linux).
• RblIncludePath – список Include директорий (для Windows).
• RblExecute – команда для запуска.
Учтите, что при каждой команде Build происходит установка ssh соединения, что требует некоторого времени (например, у меня выходило порядка 2-5 секунд).
В итоге у нас получилось заставить Visual Studio оcуществлять сборку проекта при помощи makefile и gcc из Linux.
Предположим, у нас есть программа:
#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.