enter image description here


Так получилось, что за достаточно долгую карьеру Windows и Embedded разработчика судьба свела меня по серьезному с Linux всего лишь несколько месяцев назад. Нужно было написать не очень сложную консольную программу. На тот момент все мои знания о Linux были взяты из курса по операционным системам в вузе (10 лет назад). Но Stackoverflow, google и опыт позволили достаточно быстро справиться с задачей. В итоге все было написано в Visual Studio Code под Ubuntu 14.04. Правда, приложение под Linux являлось только лишь небольшим клиентом для Windows сервера. Поэтому результат не очень удовлетворял меня, так как был оторван от основного проекта в Visual Studio. И только сейчас я смог перенести код в основной проект с помощью Visual C++ for Linux Development. В процессе мне пришлось решить несколько сопутствующих проблем. Об этом я рассажу под катом.


Итак, Visual C++ for Linux Development — это расширение для Visual Studio, позволяющее писать код в привычной многим IDE под Windows, а отлаживать его прямо в целевой операционной среде — Linux. При этом используется GCC и Remote GDB Debugger. Более подробно о расширении можно прочитать в блоге разработчиков или в переводе на хабре.


Инструкции того, как установить, запустить, настроить и т.д. можно найти по ссылкам выше. У меня с этим не возникло никаких проблем. Вопросы начались со стороны Linux системы. Напомню, что я использую Ubuntu 14.04 LTS и дальнейшее изложение пойдет именно про нее. Если кому интересно, я использовал образ для VirtualBox с сайта osboxes.org.


Также, прошу сильно меня не ругать, я все-таки в Linux далеко не гуру. Лучше подскажите, если что-то можно сделать более оптимальным путем.


Отладка первой программы


Перед тем, как использовать удаленную отладку, нужно установить несколько компонентов на Linux системе. Как указано в инструкциях по ссылке выше, это можно сделать, выполнив в командной строке следующее:


sudo apt-get install openssh-server g++ gdb gdbserver

Вызвать терминал в Ubuntu можно комбинацией клавиш Ctrl+Alt+T.


enter image description here


Я не помню, запускается ли все это хозяйство сразу или нет, по этому на всякий случай можно перезагрузиться.


Если все сделано правильно, то будет открыт порт 22. Проверить это можно используя команду nmap.


enter image description here


Но сразу подключиться из-под Visual Studio у меня не удалось, так как система почему то не пускала меня под единственным пользователем. Пришлось создать другого. Это можно сделать в System Settings > User Account.


enter image description here


При этом, не забыв нажать кнопку Unlock в верхнем правом углу.


enter image description here


Настроить подключения в Visual Studio можно в окне Tools > Options


enter image description here


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


enter image description here


При этом в Ubuntu будут скопированы исходники и собранный файл программы (если это не отключено в настройках проекта). Все это можно будет найти в папке /home/<имя пользователя>/projects.


В моем случае получилось вот так:


enter image description here


Запустить программу в самом Linux можно из консоли:


enter image description here


Теперь вроде бы можно начинать работать. Я перенес исходные файлы в Visual Studio и… ничего у меня не скомпилировалось. Оказалось, что проекту не достает .h файлов из include directories.


Подключаемые файлы


Вместе с Visual C++ for Linux Development устанавливается и множество заголовочных файлов. Их можно найти тут:


C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\Linux\include\usr

Но моему проекту этого не хватило.


В блоге разработчиков по этому поводу сказано следующее:


Getting your include files
Everyone loves IntelliSense, but we’re not yet synchronizing the include files from your Linux system. Everyone has their own ways to either share or copy these files which is great.

В будущем эту проблему обещают решить, ну а сейчас крутитесь как хотите. Там же приведен пример с копированием директории всей /usr/include с помощью PuTTY.


Но мне такой путь не нравится. Лично я предпочитаю расшарить папку с заголовочными файлами. Список директория для поиска include файлов можно посмотреть, выполнив в консоли команды


$ touch a.c
$ gcc -v -E a.c

enter image description here


Мне хватило папки /usr/include.


В случае с моей версией системы, перед тем как расшарить данную папку, нужно перевести ее во владение текущему пользователю. Делается это командой sudo chown -R osboxes:test '/usr/include'.


После этого можно открыть доступ к папке. Как это сделать написано тут.


После этого, сетевые пути можно прописать в Visual Studio как Include Directories.


Такой подход имеет преимущество в виде того, что вы будете работать всегда с оригинальными заголовочными файлами и вам не нужно будет ничего синхронизировать. С другой стороны, будут проблемы при переносе разработки на другой компьютер. Также, как я уже писал, я работаю с Ubuntu, установленной на виртуальной машине на моем компьютере. При такой конфигурации, проблемы с безопасностью уходят на второй план.


Но в других конфигурациях, действия, описанные мной выше, могут быть запрещены.


Таким образом, проблему синхронизации заголовочных файлов нужно решать исходя из условий работы. Тут выбор остается за вами.


Дополнительные команды компилятора и линкера


Заголовочные файлы стали видны и компиляция прошла успешно. Но вот слинковаться проекту не удалось. Дело в том, что я использую потоки и заголовочный файл "pthread.h". Для того, чтобы линкер увидел библиотеку pthread, нужно использовать опцию -pthread или -lpthread.


Для этих целей в Visual C++ for Linux Development есть специальная настройка:


enter image description here


Но у меня почему то она не работает. Проблема эта временная (разработчики уже знают об этом), но решать ее нужно здесь и сейчас. Обойти это ошибку можно используя другую опцию:


enter image description here


Если в место g++ написать g++ -pthread, то получится правильная строка линкера:


enter image description here
enter image description here


Тот же трюк срабатывает и для компилятора.


Запуск отладки с правами администратора


Теперь все скомпилировалось и слинковалось. Однако для работы программы нужны повышенные права, так как она открывает файл устройства ввода. Соответственно, отладку также нужно запускать с правами администратора. Сейчас в Visual C++ for Linux Development эта опция не реализована, но есть одно решение.


Можно повысить в правах gdb и gdbserver командами


$ sudo chmod ugo+s /usr/bin/gdb
$ sudo chmod ugo+s /usr/bin/gdbserver

Такой совет можно найти в комментариях в посту в блоге разработчиков.


Этот трюк работает, но он не безопасен. По сути, вы отдаете свою систему любому, кто подключается к gdbservr. В моей конфигурации это не страшно, так как все запущено на одном моем компьютере, но в других условиях нужно быть очень аккуратными с такими действиями.


Копирование дополнительных файлов


И остался последний момент. Моя программа читает настройки из текстового файла. Он является частью проекта Visual Studio и при компиляции должен копироваться в папку с исполняемым файлом.


Это можно также сделать в настройках проекта:


enter image description here


Чтобы просто скопировать файл, как остальные исходники, его можно добавить в поле Sources To Copy: @(SourcesToCopyRemotely);config.txt


А скопировать его в другую директорию можно с помощью Additional Sources To Copy.


Формат этой настройки
fulllocationpath1:=fullremotepath1;fulllocationpath2:=fullremotepath2
и т.д.


В моем случае такая строка выглядит так:


$(ProjectDir)config.txt:=$(RemoteOutDir)config.txt;

Все бы хорошо, но и тут у меня возникли проблемы.
Дело в том, что макрос $(RemoteOutDir) раскрывается в путь, начинающийся с символа "~".


Судя по всему, этот путь завязан с этой настройкой:


enter image description here


Так вот, при компиляции все работает хорошо. Но вот при копировании файлов почему то ~ воспринимается не как root директория, а просто как имя папки. То есть создается папка с именем "~":


enter image description here


Справиться с этим мне так и не удалось, поэтому я просто копировал файл config.txt вручную. Правда, для этого пришлось опять использовать изменение прав на папку:
sudo chown -R osboxes:test '/home/test'


Что в итоге


Лично я могу сказать, что Visual C++ for Linux Development extension мне помог. Несмотря на все проблемы и пару багов, он позволил мне быстрее и эффективнее решить задачу, связанную с разработкой под Linux.


Наверное, можно на это возразить, что есть более удобные пути, но я исходил только из своего опыта и знаний, а все это в основном связано с Windows.


p.s. Недавно в сети появилось видео от MSP Александра Поповкина (@Catharsis96), где он также делает обзор данного дополнения.

Поделиться с друзьями
-->

Комментарии (33)


  1. staticlab
    06.02.2017 10:30

    Скажите, насколько такой подход в целом проще и удобнее по сравнению с использованием нативных IDE для Linux, например, CLion, Netbeans, Eclipse, QtCreator, KDevelop? Дело только в привычке, или есть преимущества в разработке-сборке-отладке? Также, судя по всему, сборка идёт через MSBuild. Не помешает ли это в дальнейшем собирать проект непосредственно на линуксовой машине?


    Однако для работы программы нужны повышенные права, так как она открывает файл устройства ввода.

    Вот это не совсем понял. Вы же stdin/stdout всего лишь обрабатываете?


    1. Catharsis96
      06.02.2017 10:55
      +2

      подключение через SSH к линукс, обычное такое дело, когда нет иксов, и я могу взять Visual Studio, подключившись к линукс серверу и отлаживать нативный линуксовый код не консольным GDB отладчиком, а в Visual Studio, где он графический и несоизмеримо удобней. Автор же сделал пример с VirtualBox и иксами, но это как один из вариантов, у меня к примеру крутится виртуалка на Microsoft Azure без иксов разумеется, и подключение только по SSH. Да и в добавок, это может быть Raspberry Pi на Raspbian, а монитор по HDMI к нему подключать не всегда самый лучший вариант, поэтому я могу подключаться и отлаживать код со своей машины на Visual Studio.


    1. Catharsis96
      06.02.2017 11:10
      +1

      при использовании Visual C++ for Linux Development проект и собирается непосредственно на линуксовой машине
      image


      1. staticlab
        06.02.2017 11:13

        Но "командует" сборкой Студия, правильно?


        1. Catharsis96
          06.02.2017 11:20

          верно.


          1. staticlab
            06.02.2017 11:52

            Поэтому вопрос о том, что потребуется, если понадобится собирать проект на CI-сервере, опакечивать или, например, собирать образы для докера? Сами понимаете, что нативные проекты на C/C++ могут быть довольно нетривиальны в сборке.


            1. klirichek
              06.02.2017 16:12

              Да вся система сборки и потребуется.
              Студия тут всего лишь для разработки и отладки; она вовсе не заменяет полностью систему сборки/упаковки.
              Более того, готовый проект просто так (автоматически) в студию не перетащить: нужно вручную создавать проект, вручную добавлять исходники и настраивать солюшн. И всё ради того, чтобы иметь возможность редактировать и отлаживать.


              Вот если бы в CMake добавить в качестве таргета солюшн для студии, но под linux — было бы уже весьма неплохим вариантом.


              1. AlexandrSurkov
                06.02.2017 17:13

                По-моему в данном типе проектов Visual Studio можно использовать NMake.


    1. lieff
      06.02.2017 12:57

      К вашему списочку CodeLite еще бы добавил, он похож по структуре со студией. Тоже использовал студию для Linux разработки, через VisualGDB по моему, еще второй плагин есть и я их все время путаю. И вот надобность в плагинах уже отпала. В целом да, просто привычнее было, сейчас я уже в основном использую CodeLite и QtCreator.


      1. a1111exe
        06.02.2017 17:01

        Я бы добавил и Code::Blocks


    1. AlexandrSurkov
      06.02.2017 17:11

      Программа открывает не stdin а напрямую файл устройства ввода: \dev\input\eventXX по этому и просит sodo.
      Сборка осуществляется на удаленной машине, но контролируется Visual Studio, так что собирать все на Linux машине можно будет без проблем.

      По поводу IDE сказать сложно. Я толком не писал никогда под Linux. Но ИМХО, Visual Studio лучшая и самая удобная IDE, которой есть куча полезных дополнений :) Один ReSharper C++ чего стоит…


      1. staticlab
        06.02.2017 17:22
        +1

        Сборка осуществляется на удаленной машине, но контролируется Visual Studio, так что собирать все на Linux машине можно будет без проблем.

        Но ведь скриптов сборки нет. А если писать, то получится дублирование кода.


        Visual Studio лучшая и самая удобная IDE, которой есть куча полезных дополнений

        Не создавая холивар, но какого ещё ответа ожидать от MVP, который писал только под Windows :) Но вообще да, согласен, VS для C++ пока что лидирует.


        Один ReSharper C++ чего стоит…

        Жаль, что CLion его возможности не поддерживает.


        1. AlexandrSurkov
          06.02.2017 17:34

          При сборке код как минимум копируется на целевую машину. Можно наверное генерить руками в постбилде например из под visual studio скрипты для сборки и тоже их копировать.

          Ну а по поводу Visual Studio — конечно, другого от меня ждать сложно :) Я Code:Blocks поставил, что так им и не пользовался. Писал под Visual Studio Code в итоге. А потом переехал на этот плагин.

          Eclipse я использовал для работы с Java как то. Он очень мне не понравился. Ощущения были как будто работаешь с сырым продуктом в Alpha версии.


  1. kulinich
    06.02.2017 10:45

    По-поводу повышения прав — может можно решить эту проблему добавлением пользователя в нужную группу? Например, для доступа к последовательному порту, добавить пользователя в группу dialout.


    1. AlexandrSurkov
      06.02.2017 17:15

      Наверное можно так сделать. Мне нужен доступ к \dev\input\eventXX и возможность открыть сокет.
      Но дело в том, что я не знаю в какой конфигурации будет работать софтина у заказчика. Будем этот вопрос с ними прояснять позже.


  1. Taragolis
    06.02.2017 11:07
    +1

    Но сразу подключиться из-под Visual Studio у меня не удалось, так как система почему то не пускала меня под единственным пользователем. Пришлось создать другого. Это можно сделать в System Settings->User Account.

    А у пользователя есть пароль? По умолчанию запрещено подключаться по SSH к пользователю без пароля, можно поменять соответствующую настройку PermitEmptyPasswords


    $ sudo -e /etc/ssh/sshd_config

    Хотя это действие и не рекомендуется (лучше все же поставить пароль), однако на поиграться можно.


    если проблема не в этом, тогда надо смотреть вывод лога после попытки подключения:


    tac /var/log/auth.log | less


    1. AlexandrSurkov
      06.02.2017 17:17
      +1

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

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


      1. Taragolis
        06.02.2017 22:41

        А как же чувство спортивного интереса? Я бы еще предположил, что в вашем образе пользователь по умолчанию — root (с какого-то времени по умолчанию стал запрет на подключения root-ом по паролю), интересен уже вывод :


        echo $(id -u)


        1. Taragolis
          06.02.2017 23:08
          +1

          Больше на интерес пробило меня, в итоге скачал образ и подключился без проблем


          Вывод консоли
           23:00:56 ? ~ ?
          $ ssh osboxes@localhost -p 4422
          The authenticity of host '[localhost]:4422 ([127.0.0.1]:4422)' can't be established.
          ECDSA key fingerprint is SHA256:STXIEoIBOaHeTKu5dzBigsfWri6TmRCeAlZ+JeA4GtM.
          Are you sure you want to continue connecting (yes/no)? yes
          Warning: Permanently added '[localhost]:4422' (ECDSA) to the list of known hosts.
          osboxes@localhost's password: 
          Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 4.4.0-31-generic x86_64)
          
           * Documentation:  https://help.ubuntu.com/
          
          0 packages can be updated.
          0 updates are security updates.
          
          The programs included with the Ubuntu system are free software;
          the exact distribution terms for each program are described in the
          individual files in /usr/share/doc/*/copyright.
          
          Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
          applicable law.
          
          osboxes@osboxes:~$ echo $(id -u)
          1000
          


        1. AlexandrSurkov
          08.02.2017 10:42

          То же самое. Выводится 1000


  1. A1ien
    06.02.2017 16:15
    +2

    Давно наблюдаю за этим плагином под VS, но пока от его использования останавливает одно — есть куча сборок (кроскомпиляторов) GCC под windows, при этом компилирущих не только под x86 но и например под arm, но прикрутить такой кроскомпиятор к этому плагину пока что, увы ни как:( А это очень сильно ограничивает сферу применения, например у меня есть проект, целевая платформа которого — ARM Linux(raspbery pi, orange pi, итп), но он использует boost, и собирать его на arm linux, просто нереально долго, а иногда и памяти не хватает компилятору:( Если бы можно было настроить кроскомпиляцию при помощи VS а отладку на целевой платформе… Мечты…


    1. AlexandrSurkov
      06.02.2017 17:19

      Я вот тоже жалею об этом. Только в другом направлении. Мне интересней делать компиляцию под ARM микроконтроллеры. Я как раз сейчас пинаю разных ответственных людей из Microsoft на эти темы, но пока никакого вразумительного ответа от них не получил.


  1. mad_celt
    06.02.2017 17:20
    +1

    Но вот при копировании файлов почему то ~ воспринимается не как root директория, а просто как имя папки

    Попробуйте в Remote Build Root Directory вместо ~/projects вписать /home/test/projects, обычно в таких случаях помогает.


    1. AlexandrSurkov
      06.02.2017 17:21

      Я попробую, но есть вероятность сломать все пути :) А вообще я уже отправил в MS описание этого глюка. Они обещали разобраться.


  1. AlexandrSurkov
    06.02.2017 18:37
    -2

    Кстати, я еще умею создавать «ярлыки» (.desktop файлы), которые позволяют запускать консольные приложения в графической среде, добавлять их в автозагрузку и отключать спящий режим :) Если кому нужно — могу дописать в статье.


  1. Droid924
    06.02.2017 21:49
    -2

    Странная статья. Не очень понял, на кого она рассчитана. Вы показываете, как не разбираясь в устройстве Linux, не вникая в соглашения этой ОС, игнорируя практики разработки под Unix-like системы, разработывать что-то через GUI.


    • Что-то не получается?
    • chown с максимальными привелегиями.


    • Добавить пользователя?
    • Использовать gui.

    Эти подходы, наверняка, хорошо работают в Windows, где на каждый чих нужно продавить десяток кнопок в специально для этого сделанных программах. Это, кстати, хорошо видно, на примере указания удалённой директории. Но это совершенно не Unix-way.


    Выглядит это всё как заколачивание гвоздей микроскопом.


    1. medvedevia
      06.02.2017 22:15

      Странный коммент. Этим Вы показываете как невнимательно читаете
      А встатье написано:

      Так же, прошу сильно меня не ругать, я все-таки в Linux далеко не гуру. Лучше подскажите, если что-то можно сделать более оптимальным путем.

      .


      1. Droid924
        06.02.2017 22:27
        +1

        Ну будьте честны, эта ремарка в статье для красного словца. Если бы у автора действительно были сомнения в принятых им решениях и подходах, он бы не писал эту статью, не делал бы аккуратные скриншоты и не упомянал бы обязательное нажатие кнопки Unlock.


        1. AlexandrSurkov
          07.02.2017 14:20

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

          Устройство Linux на уровне архитектуры, как и устройство операционных систем в принципе, я вполне понимаю. Вопрос в деталях. И если бы я начал с того, что пошел бы изучать «соглашения ОС» читать man'ы и пытаться сделать из себя Linux разработчика — я бы наверное добился бы гораздо более «правильного» с точки зрения экосистемы Linux результата. Но потратил бы на это, допустим, пол года.

          А задачу нужно было решать здесь и сейчас с теми навыками, которые есть. Вот и получился такой результат, который вполне удовлетворяет заказчика в рамках поставляемой системы. И при этом, потрачено было максимум 2 недели с учетом написания статьи.

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


          1. Droid924
            07.02.2017 15:02

            Другими словами вы поддерживаете подход "оп-хлоп и в продакшн". Я верно понимаю ваши слова о "задачу нужно было решать здесь и сейчас с теми навыками, которые есть"?


            И пожалуйста не говорите про полгода изучения соглашений — это какая-то с потолка взятая оценка. Разработчик с вашим опытом должен бы догадываться о таких вещах.


            Меня вообще удивляет, что я веду такой диалог с человеком, который имеет за плечами больше 10 лет разработки, да ещё и является руководителем отдела.


            1. AlexandrSurkov
              08.02.2017 10:37

              Вы правы, это действительно в некотором роде «оп-хлоп и в продакшн». И дело не в Visual C++ for Linux Development, а в самом подходе. Вы рассматриваете происходящее в отрыве от контекста. Поверьте, дело не в лени, неумении или не знании. Это задача не стоит того, чтобы выделять на нее хоть какие-то серьезные ресурсы. И решена она была соответствующим образом. Мы же не подводную лодку строим. В любом случае, поднятые вами вопросы выходят за рамки статьи.

              В процессе работы я столкнулся с конкретными трудностями, с которыми скорее всего столкнется множество других пользователей данного расширения для VS. В статье написано то, как с этими трудностями можно справиться. Не более того.


  1. PixRaider
    07.02.2017 16:41
    +2

    Знаете, мне кажется вы все же лукавите.

    Допустим, что мотивация всего вашего туториала — это создание некоторого маленького консольного удалённого клиента на Linux-машине, который будет общаться с Win-сервером. В таком случае, учитывая уровень ресурса, да и ваш многолетний стаж, расписывать базовые шаги с картинками — ну это как-то несерьёзно. Особенно с случае с Linux, в которой ведётся значительная часть разработки(веб, мобильная etc.) в индустрии в 2017 году.

    Поэтому рискну предположить, что данный исключительно DevOps туториал на уважаемом ресурсе нацелен на юные неокрепшие умы, которые хочет заполучить/заполучила Microsoft Student Partners.

    По содержанию, это словно въехать на огромном глубоком мягком кожаном кресле в мастерскую, пробив при этом дверь, выломать панель управления и воткнуть туда свой здоровенный кабель и уехать, пробив ещё и ворота.
    Думаю можно было и просто зайти, оглядеться, прочитать технику безопасности на двери, взять пару простых инструментов и сделать ту несложную задачу, о которой вы говорили.
    Да, пришлось бы выбраться из зоны комфорта, осмотреться повнимательней на новой территории, но поверьте и вас, и ваших читателей это бы только обогатило.


    1. AlexandrSurkov
      08.02.2017 10:13

      Отличная аналогия! В чем-то вы правы. «Выбраться из зоны комфорта, осмотреться повнимательней на новой территории» безусловно было бы на много полезнее, но всему есть своя цена, в данном случае выражающаяся в потраченном на это времени.

      В любом случае, статья вызвала такие эмоциональные комментарии, а значит была написана не зря. И люди, прочитав все это, как минимум получат тему для размышления.