MacのVSCodeでC++を書く環境構築

c++vscode

(追記:2021-02-05) 今はdevcontainerで環境を作っている。mirosoft/vscode-remote-try-cppをコンテナで開くだけでbits/stdc++.hも読めるg++環境が立ち上がる。GitHubのテンプレートとして公開されているので、これをベースとしたリポジトリを作成できる。

VSCodeのRemote DevelopmentでSageMakerのコンテナ環境でモデルを開発する - sambaiz-net

Extension

を入れてHello Worldを書いたところ、stdio.hが見つからず#includeの行に赤線が付いた。

#include <stdio.h>

int main(void)
{
    printf("Hello World!\n");
    return 0;
}

Command Palletteから C/C++: Edit Configurations (JSON) を選ぶと .vscode/c_cpp_properties.json が生成されるので編集していく。

Xcode 10から/usr/includeにHeaderファイルが置かれなくなったようなのでincludePathにXcodeのSDKのパスを追加する。

$ xcode-select --install
$ xcrun --show-sdk-path
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk

$ ls -l /Library/Developer/CommandLineTools/SDKs/
total 0
drwxr-xr-x  7 root  wheel  224  7 23 08:49 MacOSX.sdk
lrwxr-xr-x  1 root  wheel   10  7 23 08:48 MacOSX10.14.sdk -> MacOSX.sdk

$ ls /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ | grep "stdio.h"
_stdio.h
stdio.h

ついでにcompilerPathをclangにした。これはIntelliSenseをうまく働かせるための設定らしい。 clangはLLVMバックエンドのC/C++コンパイラで、Macだとgccコマンドもclangを指すようになっている。

$ gcc -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)

$ clang -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)

c_cpp_properties.json はこんな感じになった。

{
    "configurations": [
        {
            "name": "Mac",
            "includePath": [
                "${workspaceFolder}/**",
                "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/**"
            ],
            "defines": [],
            "macFrameworkPath": [],
            "compilerPath": "/usr/local/bin/clang",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}

これで赤線が消えた。補完や定義ジャンプ、コードフォーマッタも効いている。

Debug

F5でStart Debuggingすると .vscode/tasks.json.vscode/launch.json が生成され、ビルド後デバッグが始まる。

$ cat .vscode/tasks.json
{
    "tasks": [
        {
            "type": "shell",
            "label": "clang++ build active file",
            "command": "/usr/bin/clang++",
            "args": [
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "/usr/bin"
            }
        }
    ],
    "version": "2.0.0"
}

$ cat .vscode/launch.json
{
    // 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": "clang++ build and debug active file",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [], // you can pass values to stdin with ["<", "test.dat"] 
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "lldb",
            "preLaunchTask": "clang++ build active file"
        }
    ]
}

Debug中

bits/stdc++.h

競プロで使われる全部入りHeader bits/stdc++.h はclangでは提供されていないので必要ならgcc(g++)でビルドする。 gccのheaderをコピーしincludePathに含めてclangでビルドしてみたところ、いくつかの存在しない依存Headerを取り除く必要があった。

$ brew install [email protected]
$ gcc-8 -v
gcc version 8.3.0 (Homebrew GCC 8.3.0_2)

$ cp /usr/local/Cellar/[email protected]/8.3.0_2/include/c++/8.3.0/x86_64-apple-darwin18/bits/stdc++.h .

AC Library

競プロで良く使われるデータ構造などが実装されているライブラリ。付属のexpander.pyを実行すればAtCoder以外にも提出できるコードが生成される。 Releasesから最新ファイルのzipファイルをダウンロードしてその中のatcoderディレクトリのパスを環境変数CPLUS_INCLUDE_PATHに追加する。

inv_mod()でモジュラ逆数を求めてみる。

剰余を取った値の四則演算 - sambaiz-net

#include <bits/stdc++.h>
#include <atcoder/all>

using namespace std;
using namespace atcoder;

#define ll long long

int main() {
    ll a = inv_mod(50, 3); // 2
    cout << a << endl;
}

Snippet

snippet generatorで生成した設定をPreferences > UserSnippetのファイルに貼り付けると、 prefixから補完されるようになる。

$ cat .vscode/compe.code-snippets
{
	"compe_main": {
		"prefix": "cm",
		"scope": "cpp",
		"body": [
		  "#include <bits/stdc++.h>",
		  "using namespace std;",
		  "",
		  "int main() {",
		  "  $1",
		  "}"
		],
		"description": "compe_main"
	}
}

補完

参考

macOS Catalina(10.15) の Xcode11 だと /usr/include が無い - Qiita

AtCoder青になったので競技プログラミングの話 - DNEK’s blog