LoginSignup
8
10

More than 5 years have passed since last update.

Visual Studio+Cygwinでコマンドライン開発環境の構築

Last updated at Posted at 2017-04-11

Copyright (c) 2017 Mamoru Kaminaga
mkaminaga

対象読者

  • Microsoft Visual Studio のコンパイラ・リンカを Cygwin から叩きいた方
  • C++ Windows プログラミングのコマンドライン開発環境について調べている方

はじめに

コマンドライン開発には, お気に入りのエディタで編集できる, ビルドの流れに対する理解が深まるなどの利点があります.
この記事では Microsoft Visual Studio Community の最新版である "Microsoft Visual Studio Community 2017" (以下 Visual Studio) と "Cygwin" を導入し, Windows アプリケーションの C++ によるコマンドライン開発環境を構築します. そして, 実際にプロジェクトのビルドを行います.

以下の点についてご了承ください.

  • この記事を参考にしたことによって生じたすべての障害・損失・不具合などに関しては, 著作権者である私と私の関係者および私の所属するいかなる団体・組織とも一切の責任を負いません. 各自の責任において参考にして下さい.
  • 筆者はプロではありません. 内容は自己流です.
  • 環境変数を弄ります.
  • Visual Studio はバージョンアップで導入方法が大きく変わる可能性があります.
  • (筆者の初投稿記事です)

環境変数の設定は不要です. 追記をお読みください (2017/04/15)

記事の検証について

この記事の内容は以下のスペックの PC で検証しました.

  • OS: Windows 7 Home Premium
  • プロセッサ: Intel(R) Core(TM) i5 CPU M 560 @2.67GHz 2.67GHz
  • 実装メモリ: 4.00 GB (3.80GB使用可能)
  • システムの種類: 64ビットオペレーティングシステム
  • ペンとタッチ: 利用不可

まずはツールのインストールだ!

Visual Studio と Cygwin のインストールを行います.
両者はフリーで利用できます.

Cygwin の導入

インストール

Cygwin の導入方法についてはすでに多くの丁寧な記事がネットに上がっているので, 説明はそれらの記事に譲ります.
Cygwin インストール などが参考になるかと思います.

文字コードの設定

コンパイラのエラー・警告メッセージの文字化け対策として, Cygwin の文字コードを設定します. 画面上で右クリックで Options を選択し, リストからText の設定画面を開きます. Localeja_JP, Charactor setSJIS にします.

Visual Studio の導入

Visual Studio の導入には少々注意が必要です.

インストーラのダウンロード

Microsoft の web ページから Visual Studio のインストーラをダウンロードします.
Visual Studio Community

インストーラの起動

インストーラを起動し, 「続行」を押選択します.

インストール項目のチェック

以下の項目に追加でチェックを入れておく必要があります.

  • 「ワークロード」の「C++ によるデスクトップ開発」
  • 「個別のコンポーネント」の「MFCとALTのサポート (x86とx64)」
  • 「個別のコンポーネント」の「WIndows 8.1 SDK」
  • 「個別のコンポーネント」の「Windows Universal CRT SDK」
  • 「個別のコンポーネント」の「標準ライブラリモジュール」

ここがポイントです. 実は検証時に 「個別のコンポーネント」の4箇所にチェックを入ていなかったためコンパイラ・リンカなどがインストールされませんでした. 再度インストーラを起動し, チェックを入れてインストールを「変更」したところ, うまく導入できました. 忘れずにチェックを入れてください.

この設定は以下の記事を参考にしました.
Visual Studio 2017 Community をインストール

インストールの開始

右下の方にある「インストール」を押します.

インストール完了まで待機

インストールにはまとまった時間が必要です.

PC の再起動

インストールが完了すると, 「セットアップに失敗しました」というダイアログが表示されますが, とりあえず「OK」を押してください. そして「再起動」を押すと, PC が再起動されます.

Visual Studio の起動

PCが再起動したら, すべてのプログラムなどから Visual Studio を起動してください.

サインイン

マイクロソフトアカウントがなけば「サインアップ」してください.

メールアドレスとパスワードを聞かれます.
入力後, 「サインイン」を押してください.

パスワードを聞かれます.
パスワードを入力後, 「サインイン」を押してください.

起動

「Visual Studio の開始」を押します.

これで Visual Studio の導入も完了です.
ここからが勝負です!

環境変数を弄るぞ!

環境変数の手動設定は不要です. 追記をお読みください (2017/04/15)

@javacommons さんが vcvarsall.bat で指定された環境変数 LIB LIBPATH INCLUDE を自動で追加, 削除するBATファイル vc2017-env.bat を公開されました.
Visual C++ 実行に必要な環境変数をいつでも使えるように予め設定しておく方法 (vcvarsall.bat で設定される変数をユーザー環境変数に自動反映するツールを作りました!【完璧バージョン】)
この章の方法で手動で設定するよりも, vc2017-env.bat を使わせていただく方が早いです.(2017/04/30)

環境変数は多くのプロセスが参照しており, 誤った変更をするとPCの動作が不安定になる危険性があります. 環境変数を復旧できるよう, 変更履歴を記録することを勧めします.
環境変数自体の扱い方についても多くの丁寧な記事がネットに上がっているので, 説明はそれらの記事に譲ります.
以下のページなどが参考になるかと思います.
環境変数の設定方法

また, ここに書いていあるパスは検証環境でのものです. バージョンや環境による違いがある可能性があります. ここに書いてあるパスをコピーアンドペーストするのではなく, それに相当するパスを必ず自分で探してください.

実行可能ファイル (*.exe) にパスを通す

ビルドの際に直接必要となる実行可能ファイルは以下の4つです. これらは経験的にビルド過程で必要と判明しているだけで, 同じフォルダにある他のEXEを内部で呼び出しているかもしれません. そのためフォルダごと PATH に追加してしまいます.

コンパイラ (cl.exe):
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\cl.exe

リンカ (link.exe):
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\link.exe

メイク (nmake.exe):
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\nmake.exe

リソースコンパイラ (rc.exe):
C:\Program Files (x86)\Windows Kits\8.1\bin\x86\rc.exe

また, スタティックリンクライブラリの作成時には以下の実行可能ファイルが必要です.

ライブラリマネージャー (lib.exe):
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\lib.exe

重複を省き, 環境変数 PATH に以下の2フォルダを追加します.

  • C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86

  • C:\Program Files (x86)\Windows Kits\8.1\bin\x86

ヘッダファイル (*.h) にパスを通す

Windows プログラミングに必要となるヘッダファイルは以下のフォルダに分かれて存在します. 環境変数 INCLUDE にこれらを追加します.
(ここで不足があるとコンパイラエラーに苦しむことになります)

ユーザモードとカーネルモードで使われるヘッダ:
C:\Program Files (x86)\Windows Kits\8.1\Include\shared

Windows プログラミングのヘッダ:
C:\Program Files (x86)\Windows Kits\8.1\Include\um

C++11 標準ライブラリのヘッダ:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include

C 標準ライブラリのヘッダ:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt

WinRT API のヘッダ:

  • C:\Program Files (x86)\Windows Kits\8.1\Include\winrt
  • C:\Program Files (x86)\Windows Kits\8.1\Include\winrt\wrl
  • C:\Program Files (x86)\Windows Kits\8.1\Include\winrt\xaml

スタティックリンクライブラリ (*.lib) にパスを通す

必要なすべてのスタティックリンクライブラリにパスを通す必要があります.
以下のフォルダを環境変数 LIBLIBPATH に追加します.
(ここで不足があるとリンカエラーに苦しむことになります)

  • C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86
  • C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86
  • C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\lib\x86
  • C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\lib\x86\store

以上で環境変数の設定は完了です, お疲れ様でした.
PCを再起動してこれらの変更を反映させてください.

コマンドライン開発, やるぞー!

設定がうまくできているかを確認するために, 簡単な仕事をいくつかこなしてみましょう.

単ファイルで "Hello World!"

お約束の "Hello World" です.
以下の一連のコマンドを Cygwin のターミナル上で実行してください.

mkdir level1
cd level1/
cygstart notepad main.cc
cl /W4 /D"UNICODE" /D"_UNICODE" /EHsc main.cc
./main.exe

notepad とはメモ帳のことです. cygstart notepad main.cc ではメモ帳で以下の内容をコピーして保存ください.

main.cc
#include <wchar.h>
#include <windows.h>
#include <string>
int wmain(int argc, const wchar_t* argv[]) {
  std::wstring hello(L"Hello World!");  // C++ STL compilation and link check.
  wprintf(L"%ls", hello.c_str());  // STL compilation and link check.
  return 1;
}

実行結果:

"Hello World!" ができた方, 環境構築は成功です. おめでとうございます!

もしもコンパイルエラーやビルドエラーが発生してしまった場合は, 環境変数の設定方法が誤っている可能性があります. もう一度よく確認してみてください.

複数ファイルで "Hello World!"

実際のプロジェクトでファイルが1つだけしか扱えないのは不便です.
複数のソースファイルをまとめてビルドする方法を確認します.
以下の一連のコマンドを Cygwin のターミナル上で実行してください.

mkdir level2
cd level2/
cygstart notepad main.cc
cygstart notepad hello.cc
cl /c /W4 /D"UNICODE" /D"_UNICODE" /EHsc main.cc
cl /c /W4 /D"UNICODE" /D"_UNICODE" /EHsc hello.cc
"/cygdrive/c/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.10.25017/bin/HostX86/x86/link.exe" /SUBSYSTEM:CONSOLE main.obj hello.obj
./main.exe

cygstart notepad main.cc ではメモ帳で以下の内容をコピーして保存ください.

main.cc
#include <wchar.h>
#include <windows.h>
void say_hello_world();  // Function decleration
int wmain(int argc, const wchar_t* argv[]) {
  say_hello_world();
  return 1;
}

cygstart notepad hello.cc ではメモ帳で以下の内容をコピーして保存ください.

hello.cc
#include <wchar.h>
#include <windows.h>
#include <string>
void say_hello_world() {  // Function definition
  std::wstring hello(L"Hello World!");  // C++ STL compilation and link check.
  wprintf(L"%ls", hello.c_str());  // STL compilation and link check.
}

なお, link.exe をフルパスで呼び出しているのは Cygwin のパッケージに含まれる GNU の link.exe と名前が衝突してしまうためです.

実行結果:

これで複数ファイルのビルドもできるようになりました!

makefile による自動化

先の例で複数ファイルをビルドする際, コンパイラ・リンカのコマンドを3回叩きました.
これだと, ファイルが増えるたびにコマンドをたたかなければなりません.
腱鞘炎になりそうです...
一連のビルドコマンドを自動化するために, makefileを作りましょう.
level2\makefile という名前のファイルを作成し, 以下の内容をコピーしてください.

CC = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\cl.exe"
LINK = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\link.exe"

TARGET = main.exe
SRC = main.cc hello.cc
OBJS = main.obj hello.obj

CPPFLAGS = /W4 /Zi /O2 /MT /D"UNICODE" /D"_UNICODE" /EHsc
LFLAGS = /SUBSYSTEM:CONSOLE

ALL: $(TARGET)

$(TARGET): $(OBJS)
    $(LINK) $(LFLAGS) /OUT:$(TARGET) $(OBJS)

.cc.obj:
    $(CC) $(CPPFLAGS) /c $<

そして main.obj, hello.objmain.exe を一度削除し, Cygwin のターミナル上で nmake と叩いてみてください.

実行結果:

これで複数ファイルのビルドが自動化されました.

スタティックリンクライブラリの作成と使用

先の例ではソースファイル hello.cc から オブジェクトファイル hello.obj を作成し, それをオブジェクトファイル main.obj とリンクしました.
ここではオブジェクトファイル hello.obj からスタティックリンクライブラリ hello.lib を作成し, main.obj とリンクします.

ソースコードは先ほどの hello.ccmain.cc を使いまわします.
以下の一連のコマンドをCygwin のターミナル上で実行してください.

mkdir level3
cp level2/*.cc level3
cd level3
cl /c /W4 /D"UNICODE" /D"_UNICODE" /EHsc main.cc
cl /c /W4 /D"UNICODE" /D"_UNICODE" /EHsc hello.cc
lib hello.obj
"/cygdrive/c/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.10.25017/bin/HostX86/x86/link.exe" /SUBSYSTEM:CONSOLE main.obj hello.lib
./main.exe

実行結果:

"Hello World!" が実行できました!

実際にプロジェクトをビルドしてみる

これは整備した開発環境で実際にプロジェクトをビルドするといオマケです.
筆者の公開しているモールス信号生成ソフトウェアをビルドします (ステマです).
モールス信号で "Hello World!" しようというわけです.

以下のリリースページから v_1.1.1 のソースコードをダウンロードします.
「cwconv」リリースページ

以下の手順でビルドします.

  1. ダウンロードしたアーカイブを解凍します
  2. Cygwin で展開先の makefile のあるディレクトリに侵入します.
  3. build というフォルダを一時ファイル生成用に作成します.
  4. makefileCC={cl.exeのフルパス}LINK={link.exeのフルパス}を環境に合わせて書き換えます.
  5. nmake を実行し cwconv.exe を作成します.

cwconv.exe -s Hello world を実行すると, PC のスピーカーからモールス信号で "Hello World!" が再生できました!

最後に

ここで紹介した開発環境は, あくまで最低限のビルドをサポートするものです.
Cygwin で様々なパッケージをインストールすることで, スペシャルな開発環境を育て上げることができます.
つたない記事でしたが, 少しでもお役に立てれば幸いです.

サンプルプログラム

追記

環境変数を用いないベターな方法 (2017/04/15)

コメントで nmake ですべてできるのではないのかというご指摘を頂いたので確認しました.
設定した環境変数 PATH, INCLUDE, LIB, LIBPATH を一旦削除します.
「makefile による自動化」で使用した makefile にて, 環境変数 INCLUDE で指定していたパスをコンパイラオプションの /I で指定し, 環境変数 LIB, LIBPATH で指定していたパスをリンカ―オプション /LIBPATH で指定します.
変更後の makefile は以下のようになります.

makefile
CC = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\cl.exe"
LINK = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\bin\HostX86\x86\link.exe"

TARGET = main.exe
SRC = main.cc hello.cc
OBJS = main.obj hello.obj

CPPFLAGS = /W4 /Zi /O2 /MT /D"UNICODE" /D"_UNICODE" /EHsc\
/I"C:\Program Files (x86)\Windows Kits\8.1\Include\shared"\
/I"C:\Program Files (x86)\Windows Kits\8.1\Include\um"\
/I"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include"\
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt"\
/I"C:\Program Files (x86)\Windows Kits\8.1\Include\winrt"\
/I"C:\Program Files (x86)\Windows Kits\8.1\Include\winrt\wrl"\
/I"C:\Program Files (x86)\Windows Kits\8.1\Include\winrt\xaml"

LFLAGS = /SUBSYSTEM:CONSOLE\
/LIBPATH:"C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86"\
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86"\
/LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\lib\x86"\
/LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\lib\x86\store"

ALL: $(TARGET)

$(TARGET): $(OBJS)
    $(LINK) $(LFLAGS) /OUT:$(TARGET) $(OBJS)

.cc.obj:
    $(CC) $(CPPFLAGS) /c $<

この makefile を用いて hello.ccmain.cc からのビルドに成功しました.
環境変数 を弄らずともビルド環境は容易に構築できました...

nmake を用いずに直打ちでコンパイルする際などのために, /I オプションと /LIBPATH オプションをデフォルトで追加するようなエイリアスをきっておくと便利かもしれません.

vcvarsall.bat を用いたより良い方法 (2017/04/15)

vcvarsall.bat を実行してシェルを立ち上げる以下のバッチファイルを利用すれば, makefile でいちいちパスを追加せずともビルドできる環境を構築することができました.

cygwin_for_VS.bat
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 8.1
start C:\cygwin64\bin\bash.exe --login

このバッチファイルの作成にあたっては以下のサイトを参考にしました.
「Cygwin Terminal に Visual Studio の環境設定を追加する方法」

このバッチファイルをダブルクリックでターミナルを起動します.
「makefile による自動化」で使用した makefile を使用したところ, 簡単にビルド環境が構築できました.

STL などのプログラム共通で使用するライブラリはこの方法で勝手に参照されるようにしておき, よそから持ってきた一部のプロジェクトでしか使用しないライブラリは makefile で指定するなどの使い分けができるかと思います.

参考

Cygwin
Cygwin インストール
Visual Studio 2017 Community をインストール
環境変数の設定方法
Windows 8 SDK: Include files in "shared", "um", and "winrt" directories. What's the difference?
コンパイラ オプション
リンカー オプション
LIB の実行
Cygwin Terminal に Visual Studio の環境設定を追加する方法
Visual C++ 実行に必要な環境変数をいつでも使えるように予め設定しておく方法 (vcvarsall.bat で設定される変数をユーザー環境変数に自動反映するツールを作りました!【完璧バージョン】)

変更履歴

2017/04/11 初版投稿
2017/04/11 ↑の数分後, フォーマット整形してあげ直し
2017/04/12 スタティックリンクライブラリ, プロジェクトのビルドについて掲載
2017/04/12 タイトルの誤字修正. VisauStudio -> Visual Studio, その他誤字修正
2017/04/15 makefile ですべてこなす方法を追記, vcvarsall.bat を用いた方法を追加
2017/04/30 @javacommons さんの vc2017-env.bat を紹介
2017/05/02 編集リクエストを頂いた誤字の修正

8
10
17

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10