MSYS2 VSCode gccオプション設定プログラム


MSYS2で、Rustの開発環境が作れるようになった。
pacman -S mingw-w64-x86_64-rust

このRustは、rustupが含まれておらず、cargoを使い、MSYS2gccコンパイラが使える。

Rustで画面を作ろうとすると、gtk-rsが簡単そうだ。
MSYS2でGTK3をインストールして
pacman -S mingw-w84-x86_64-gtk3
画面設計用のGladeも入れておけば、楽だろう。
pacman -S mingw-w64-x86_64-glade

cargo側の設定で、cargo.toml[dependencies]にGTKを設定すれば、自動的にcrates(クエート)がダウンロードされる。

しかし、VSCodeで開発する際は、gccのコンパイルオプションを書くのが面倒くさい。

そこで、MSYS2に付属している、Pythonを使って、tasks.jsonなどに書き込むプログラムを書いてみた。

使い方

(1) main関数のvscodePath を設定する
(2) main関数のpkgList を設定する (ここでは、GTK3)
(3) setProperties関数のjsonName を設定する (ここでは、C/C++用)
(4) setTasks関数の"-mwindows"は、win10で、コンソール画面を非表示にできる gccオプションです。必要なければ、この行をコメントアウトしてください。
(5) 後は、実行するだけ (必要なパッケージは、何度 追加して実行しても、自動で重複削除しています)

解説

MSYS2のtoolchainに付属のpkg-cofigコマンドを使って、必要な情報を得て、tasks.jsonc_cpp_properties.jsonに書き込んでいます。

pkg-cofigコマンドは、MSYS2でインストールできる。
pacman -S mingw-w64-x86_64-toolchain

このプログラムは、gccコンパイラを使うのであれば、Rust以外でも使える。
パッケージ名を設定すれば、GTK以外でも、いろいろ使える

pyPkgConfig.py
# This Python file uses the following encoding: utf-8
import sys
import subprocess
import os
import json

def getFlags(pkgList):
    ListA = []
    for itemP in pkgList:
        result = subprocess.run(["pkg-config", "--cflags-only-I", itemP], encoding="utf-8", stdout=subprocess.PIPE)
        ListB = result.stdout.split()

        for itemB in ListB:
            itemB = setAbsPath("-I", itemB)
            ListA.append(itemB)

        ListA = uniList([], ListA)

    return ListA

def getLibs(pkgList):
    ListA = []
    for itemP in pkgList:
        result = subprocess.run(["pkg-config", "--libs", itemP], encoding="utf-8", stdout=subprocess.PIPE)
        ListB = result.stdout.split()

        for itemB in ListB:
            itemB = setAbsPath("-L", itemB)
            ListA.append(itemB)

        ListA = uniList([], ListA)

    return ListA

def setAbsPath(head, Path):
    result = Path
    if head == Path[:2]:
        result = Path[2:]
        result = os.path.abspath(result)
        result = head + result

    return result        

def getFullPath(flagsList):
    List = []
    for item in flagsList:
        if item[:2] == "-I":
            fullPath = item[2:]
            if os.path.isdir(fullPath):
                List.append(fullPath)

    List = uniList([], List)
    return List

def getInculdePath(pathList):
    List = []
    for item in pathList:
        fullPath = item
        lowPath = fullPath.lower()
        pos = lowPath.find("/include")
        if pos > 0:
            fullPath = fullPath[:pos + 8]
            fullPath = fullPath + "/**"
            List.append(fullPath)

    List = uniList([], List)
    return List

def uniList(ListA, ListB):
    ListC = []

    ListC = ListA
    for itemB in ListB:
        notFind = True
        for itemA in ListA:
            if itemA == itemB:
                notFind = False
                break

        if notFind:
            ListC.append(itemB)

    return ListC

def setTasks(vscodePath, flagsList, libsList):
    jsonName = "/tasks.json"
    jsonPath = vscodePath + jsonName

    with open(jsonPath, mode="r", encoding="utf-8") as rf:
        jsonFile = json.load(rf)
        for item in jsonFile["tasks"]:
            itemList = item["args"]
            itemList = uniList([], itemList)
            itemList = uniList(itemList, flagsList)
            itemList = uniList(itemList, libsList)
            itemList = uniList(itemList, ["-mwindows"])
            item["args"] = itemList

    with open(jsonPath, mode="w", encoding="utf-8") as wf:
        json.dump(jsonFile, wf, indent=4, ensure_ascii=False)

def setProperties(vscodePath, incsList):
    jsonName = "/c_cpp_properties.json"
    jsonPath = vscodePath + jsonName

    with open(jsonPath, mode="r", encoding="utf-8") as rf:
        jsonFile = json.load(rf)
        for item in jsonFile["configurations"]:
            itemList = item["includePath"]
            itemList = uniList([], itemList)
            itemList = uniList(itemList, incsList)
            item["includePath"] = itemList

    with open(jsonPath, mode="w", encoding="utf-8") as wf:
        json.dump(jsonFile, wf, indent=4, ensure_ascii=False)

def main():
    vscodePath = "C:/work/hello/.vscode"
    pkgList = ["gtk+-3.0"]

    flgsList = getFlags(pkgList)
    libsList = getLibs(pkgList)
    pathList = getFullPath(flgsList)
    incsList = getInculdePath(pathList)
    setTasks(vscodePath, flgsList, libsList)
    setProperties(vscodePath, incsList)

if __name__ == "__main__":
    main()

GTK3を入れてみた。

tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: gcc.exe アクティブなファイルのビルド",
            "command": "C:\\msys64\\mingw64\\bin\\gcc.exe",
            "args": [
                "-g",
                "${file}",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe",
                "-IC:/msys64/mingw64/include/gtk-3.0",
                "-IC:/msys64/mingw64/include/pango-1.0",
                "-IC:/msys64/mingw64/include",
                "-IC:/msys64/mingw64/include/glib-2.0",
                "-IC:/msys64/mingw64/lib/glib-2.0/include",
                "-IC:/msys64/mingw64/include/harfbuzz",
                "-IC:/msys64/mingw64/include/freetype2",
                "-IC:/msys64/mingw64/include/libpng16",
                "-IC:/msys64/mingw64/include/fribidi",
                "-IC:/msys64/mingw64/include/cairo",
                "-IC:/msys64/mingw64/include/lzo",
                "-IC:/msys64/mingw64/include/pixman-1",
                "-IC:/msys64/mingw64/include/gdk-pixbuf-2.0",
                "-IC:/msys64/mingw64/include/atk-1.0",
                "-LC:/msys64/mingw64/lib",
                "-lgtk-3",
                "-lgdk-3",
                "-lz",
                "-lgdi32",
                "-limm32",
                "-lshell32",
                "-lole32",
                "-Wl,-luuid",
                "-lwinmm",
                "-ldwmapi",
                "-lsetupapi",
                "-lcfgmgr32",
                "-lpangowin32-1.0",
                "-lpangocairo-1.0",
                "-lpango-1.0",
                "-lharfbuzz",
                "-latk-1.0",
                "-lcairo-gobject",
                "-lcairo",
                "-lgdk_pixbuf-2.0",
                "-lgio-2.0",
                "-lgobject-2.0",
                "-lglib-2.0",
                "-lintl",
                "-mwindows"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build",
            "detail": "コンパイラ: C:\\msys64\\mingw64\\bin\\gcc.exe"
        }
    ]
}

環境設定により、完全な動作保証は、出来ていません。