In Technologie
Date

Tuto: configurer VSCode pour le C++ sous Windows avec MinGW W64, et utiliser OpenCV.

Petit tutoriel pour réussir à être opérationnel avec ce super-combo qu'est Windows + VSCode + C++ + MinGW (64) + OpenCV.

Le meilleur environnement pour coder en C++ reste Linux... Maiiiiis vous tenez à vos jeux, à Photoshop, et toutes ces choses qui ne tournent pas sous Linux... Certains vous auront conseillé de passer sous Mac comme la moitié de vos amis développeurs... Maiiiiiis vous avez besoin d'une vraie puissance matérielle et notamment graphique... Bref vous êtes sur PC et sous Windows. J'ai longtemps utilisé Code::Blocks dès sa sortie en 2005, Visual Studio aussi... maiiiis aujourd'hui, je ne sais pas vous mais moi je tiens beaucoup à VSCode, il est configuré au plugin et à la couleur près, à coté de Code::Blocks, ya pas photo. Par contre contrairement à Code::Blocks ou Visual Studio où tout est déjà prêt à l'emploi, il faut faire quelques prépas sur VSCode pour être opérationnel. Et pour OpenCV pareillement, il n'est plus distribué (sur Windows) que pour Visual Studio.

Retroussez vos manches c'est parti.

Intaller MinGW W64

Doit-on présenter MinGW ? C'est une version minimaliste de GCC (GNU Compiler Collection, compilateur phare sous Linux) pour Windows. C'est l'alternative libre à VC, compilateur de Microsoft, et au vieillissant Cygwin.

Vous trouverez l'installeur de MinGW W64 ici sur SourceForge. Vous êtes sur un Windows 64 bits ? Parfait, choisissez l'Archi x86_64, la version Threads posix, exception seh. Larguez ça sur c:\mingw. L'installeur vous fait un sous-répéertoire mingw64 dedans, j'ai mis son contenu directement dans c:\mingw histoire d'avoir des chemins plus courts à renseigner. Ainsi au lieu d'avoir le chemin c:\mingw\mingw64\bin pour le compilateur j'ai c:\mingw\bin, faites comme moi c'est plus court et donc plus simple.

N'oubliez pas de mettre une variable d'environnement vers le repertoire de votre compilateur. Pour ce faire : clic-droit sur le Poste de Travail ("ce PC") >> Propriétés >> Paramètres Système Avancés. Cliquez ensuite sur Variables d'environnement.

Variables d'environnement Windows

Dans les Variables système, double-cliquez sur Path et rajoutez la valeur c:\mingw\bin dans votre liste. Puis Ok, Ok.

Variables d'environnement Windows

Pour vérifier que c'est bon, ouvrez une invite de commande (touche Win, tapez cmd puis Entrée) ou PowerShell :), tapez y

g++ --version

Si tout va bien vous devriez avoir quelquechose comme ça :

C:\Users\wizar>g++ --version
g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

All Good :)

Configurer VSCode

Dans VSCode, allez sur l'onglet Extensions, cherchez-y c++, normalement la première extension qui apparait est la bonne : C/C++ de Microsoft (ms-vscode.cpptools), installez là.

VSCode C++ extension

Faites-vous un dossier de projet, ouvrez le dans VSCode. Créez un nouveau fichier main.cpp.

#include <iostream>

int main()
{
    std::cout << "Hey :)" << std::endl;

    system("pause");
    return 0;
}

Survolez <iostream> en appuyant sur CTRL, VSCode va créer tout seul un sous dossier .vscode avec un fichier settings.json dedans, on en aura besoin plus tard.
Créons un fichier de tâches pour VSCode. Faites CTRL + SHIFT + P pour ouvrir la palette et commencez à taper task, choisissez Tasks: Configure Task, puis choisissez g++.exe build active file. VSCode va créer un fichier tasks.json prérempli, mais on va le pimper un peu, et on le re-pimpera encore un peu plus tard.

Déjà pour la clé label, vous pouvez mettre build. Ensuite, comme vous avez mis le chemin du compilateur en variable d'environnement, vous pouvez virer le chemin dans la clé command pour ne laisser plus que g++. Vous pouvez écrire les arguments directement dans la valeur pour la clé command ou, plus pratique, passer un tableau d'argument avec la clé args.

Chez moi mon fichier tasks.json ressemble à ça pour l'instant:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558 
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "g++",
            "args": [
                "-g",
                "main.cpp",
                "-o",
                "main.exe"
            ],
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        }
    ]
}

Du coup, si vous faites CTRL + SHIFT + B maintenant vous pouvez build votre executable :)

Configurons vite-fait le débugger.
Si vous ouvrez l'onglet du Debugger de VSCode, il vous fera remarquer que vous n'avez pas de fichier launch et vous propose d'en créer un, faites donc.

debugger vscode

Au moment de la création, choisissez C++ GDB/GDL.
Dans le fichier launch.json nouvellement créé, vous devez renseigner le chemin de gdb en value de la clé miDebuggerPath. Si vous avez fait la même install de MinGW que moi, ce sera donc C:\mingw\bin\gdb.exe et n'oubliez pas d'échapper vos antislashs "C:\\mingw\\bin\\gdb.exe".
Pour la clé program utilisez la valeur "${workspaceFolder}/main.exe"
Enfin, vous pouvez rajouter une pré-étape de build en rajoutant la clé preLaunchTask avec pour valeur le nom de votre task de build créée précédemment (logiquement "build" si vous avez fait comme moi).

Mon fichier launch.json ressemble à ça :

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Lancer",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/main.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\mingw\\bin\\gdb.exe",
            "preLaunchTask": "build",
            "setupCommands": [
                {
                    "description": "Activer l'impression en mode Pretty pour gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

Voilà, votre VSCode est paré pour le C++, son debugging, et sa compilation :)

Installer OpenCV

Faites un tour sur le site officiel d'OpenCV, rubrique Releases et téléchargez la version Windows, pour moi ce sera la 3.4.9. Installez la directement à la racine du disque (pour écourter les chemins pour les futurs links, vraiment, vous n'avez pas envie de l'installer dans Program Files) : C:\opencv.
Comme pour MinGW, vous avez un sous-dossier opencv, mettez son contenu dans C:\opencv et virez le. En toute logique vous vous retrouvez donc avec un dossier build et un dossier sources dans C:\opencv.

C'est là que ça commence à devenir sympa : il va falloir se taper le build puisque l'équipe OpenCV ne fournit plus des versions prébuilt que pour VC et plus pour MinGW comme vous pouvez le voir dans C:\opencv\build\x64.

Installer CMake et compiler OpenCV

L'avantage du C++, outre ses super performances, c'est qu'il est multiplateformes. Mais qui dit multiplateforme, dit fatalement de grosses différences d'une plateforme à l'autre, plus précisemment : la merde au niveau dépendances, environnement etc etc. C'est là que le processus de construction logicielle multiplateforme entre en jeu. Pour faire le build, nous allons avoir besoin de CMake, téléchargeable sur son site officiel.
Lui vous pouvez laisser l'installeur le mettre dans Program Files.

Une fois lancé, choisissez le dossier source C:/opencv/sources, d'ailleurs normalement vous aurez remarqué qu'il s'y trouve un fichier CMakeLists.txt. Et pour Where to build the binaries, à coté des builds VC14 et VC15 : C:/opencv/build/x64/mingw64 (le dossier n'existe pas il sera créé). C'est parti, cliquez sur Configure, au prompt choisissez MinGW Makefiles pour le generateur.

CMake MinGW Makefiles

cmake

Vous pouvez cliquer sur Generate.
Une fois que c'est bon, lancez une invite de commande, déplacez vous dans le dossier du build qu'on vient de générer.

cd C:\opencv\build\x64\mingw64

Puis lancez la commande :

mingw32-make

Et là vous pouvez aller vous faire un café. En fait, vous pouvez même descendre au bar du coin pour aller prendre votre café, vous avez le temps. Sérieusement, il y en a pour plus de 2h de compile.

Maintenant qu'OpenCV est compilé, on va aussi le mettre en variable d'environnement de Windows. De la même manière que tout à l'heure, rajoutez donc C:\opencv\build\x64\mingw64\bin dans le Path des variables d'environnement système.

Configurer son projet VSCode pour OpenCV

Nous y sommes presque.
Vous vous rappelez ce fichier settings.json dans le sous-répertoire .vscode de votre projet qu'on n'a pas encore touché tout à l'heure ? Nous allons le modifier, si VSCode ne l'a pas créé, créez le.
Il va falloir spécifier le répertoire d'includes d'OpenCV pour qu'il détecte automatiquement les inclusions. Rajoutez-y donc une clé C_Cpp.default.includePath. Vous devez passer un tableau de chemins pour toutes vos dépendances, ici donc le dossier d'OpenCV :

{
    "C_Cpp.default.includePath" : [
        "C:\\opencv\\build\\include"
    ]
}

Et pour la compilation, il nous reste à rajouter en argument de la commande l'option -I spécifiant le dossier d'includes d'OpenCV et configurer le Linker du compilateur vers le dossier Lib d'openCV avec l'option -L et indiquer les dépendances (on les mettra toutes), le tout dans votre tableau d'arguments de la tache build dans votre fichier tasks.json, sans oublier d'échapper vos antislashs :

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558 
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "g++",
            "args": [
                "-g",
                "main.cpp",
                "-o",
                "main.exe",
                "-IC:\\opencv\\build\\include",
                "-LC:\\opencv\\build\\x64\\mingw64\\lib",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_calib3d349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_core349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_dnn349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_features2d349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_flann349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_highgui349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_imgcodecs349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_imgproc349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_ml349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_objdetect349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_photo349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_shape349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_stitching349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_superres349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_ts349.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_video349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_videoio349.dll.a",
                "C:\\opencv\\build\\x64\\mingw64\\lib\\libopencv_videostab349.dll.a",
            ],
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        }
    ]
}

J'espère que vous m'avez écouté quand je vous ai dit de ne pas l'installer dans Program Files, vous comprenez pourquoi maintenant ;)

Normalement, on est tout bon, il n'y a plus qu'à tester ça avec un ptit code qui va lire et afficher une image (que vous aurez pris soin de mettre dans le dossier du projet) :

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main()
{
    Mat image;
    image = cv::imread("cartman.jpg");
    namedWindow("Goddamn Hippies", CV_WINDOW_AUTOSIZE );
    imshow("Goddamn Hippies", image );

    waitKey(0);

    return 0;
}

Et ya plus qu'à compiler avec un coup de CTRL + SHIFT + B :)

Voilà.

La prochaine fois on verra pour carrément tout faire avec Docker.