2017年12月19日火曜日

Windows 環境変数適用 備忘録

環境変数を値に置き換える
#include <boost/regex.hpp>
#include <string>
#include <iostream>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

std::string getEnvValue(const std::string& str) {
  std::string result;
  std::string inp = str.substr( 1, str.size() - 2 );
  //std::cout << inp << std::endl;
  char buf[ 4096 ];
  DWORD sz = sizeof(buf);
  if( GetEnvironmentVariable( inp.c_str(), buf, sz ) > 0 ) {
    result = buf;
  }
  return result;
}

bool replaceEnv(std::string& str) {
  boost::regex r("(%[a-zA-Z0-9_]+%)");
  boost::smatch m;
  if( boost::regex_search(str, m, r) ) {
    std::string eval = m.str(1);
    std::string sval = getEnvValue( eval );
    while( std::string::npos != str.find(eval) ) {
      str.replace( str.find(eval), eval.size(), sval );
    }
    return true;
  }
  return false;
}

int main(int argc, char* argv[]) {
  std::string str = "%USERPROFILE%\\hoge\\fuga";
  while( replaceEnv( str ) ) {}
  std::cout << str << std::endl;

  

  return 0;
}

2017年12月5日火曜日

MSVCを使ったOSSのビルドについて

C++アドベントカレンダー2017のDAY5の記事になります。


皆さんOSS(オープン・ソース・ソフトウェア)のビルド、どうしてますか?
Linux 系だとパッケージメンテナーが存在していて、apt get コマンドや yum コマンド一発でビルドされたライブラリが取得できますし、プラットフォームが更新されれば、update をかませば一括してライブラリもそれに合わせて更新されます。
それに大抵は ./configure し、make し、make install で済んでしまいます。

Windows 環境でOSSを利用したい時、どうしてますか?
僕は毎回ソースをダウンロードしてから、install.txt や readme.txt やサイトを検索してビルド方法を試行錯誤していました。一度ビルドしてしまえば、当面ビルドの必要無いですしね?
現状を振り返ってみて、気がついてみれば、結構いろんなOSSを利用していました。
それに、会社ではサポートしなければならないOS等の関係もあり、長らくVisual Studio 2005を使っていました。情勢が変わって、Windows 7 の期限も近づいており、さすがに Visual Studio 2010 に切り替えました。これを契機にOSSのビルドを自動化して時間の効率化を図ろうと決意しました。

 ちょっと脱線しますが、自動化しようと思った動機について、もう少し書こうと思います。

 ひとつは、MSの提供するライブラリよりもOSSに依存した方が安全だと思った事です。ISAPI が C++でサポートされなくなったり、Regex系のライブラリが消えたり、Web系のC++ライブラリがサポートされなくなったり。特にSoapを使った独特のIDL言語を使った機構がサポートされなくなったのは、かなりの痛手です。MSのライブラリに依存することは、危険です。使いやすいからWTLでアプリを組んでいましたが、リモート・アプリケーションでのプリンタが認識できない問題で、印刷コモンダイアログを自作する羽目になりました。幸いWTLは、まだメンテナンスが行われており、Issues 等を提案すると取り込んでもらえる状況なのが救いです。Regex系のライブラリが消えた時は、移植で死にそうになりました。Soapがサポートされなくなった時は、MSはC#が大切でC++なんか気にしちゃいないと実感しました。

 もうひとつは、自社で開発している既存のソフトウェアを32bit環境から64bit環境へ移行する目論見も出てきました。移行する時にOSSライブラリを個々に調べてビルドしていたら大変です。

 最後は、あわよくばプルリクエストをもらって楽しよう共闘できると思ったからです。そんなプロジェクト、どこにも無いですし、それなりに価値があるのではないかと思っています。

そうやって作成したのが、こちら
build-oss-library-on-windows
です。

 自動化するにあたっては、いろいろと躓きました。Visual Studio の IDE を使ってコンパイルしなければならないのが面倒で調べたところ、msBuild というコマンドで IDEのプロジェクトをビルドできる事が分かりました。ところが、このIDEはバージョン依存で正しいビルドツールを指定しないとエラーでビルドできません。正しいビルドツールの番号、気が狂ってます。Visual C++ のバージョンを判定するバッチファイルの修正履歴を見ていただければ、わかると思いますが、現実は予想の斜め上を行ってました。信じらない事に Microsoft からVisual C++のバージョンに関する公式の表がどこにも掲載されていません
Visual Studio 製品名VC通称ツールセットのバージョンコメント
Visual Studio 2003VC7v70
Visual Studio 2005VC8v80
Visual Studio 2008VC9v90
Visual Studio 2010VC10v100
Visual Studio 2012VC11v110
Visual Studio 2013VC12v1202015がVC14だからVC12で合ってるか調べる羽目になったやんけ(#^ω^)ピキピキ
Visual Studio 2015VC14v140なんで一個バージョン飛んでるねん?
Visual Studio 2017VC15v141v141って殺すぞ何ぞ?(^ω^)
また、*.sln プロジェクトファイルは、それぞれのバージョンに合わせなければなりません。幸い devenv /upgrade でコマンドラインからアップグレードできるのが救いです。

 今のところ Visual Studio 2010 win32 プラットフォームでしかビルド検証されていない状況ですが、ドキュメントを参考に是非、利用してみてください。特に自前で、コツコツと毎回ビルドされている方には使ってみて欲しいです。時間の節約になると思います。そして共闘しましょう٩( 'ω' )و

 最後に…
安全という名の緊縛の言語 Java氏ね Java氏ね Java氏ね 

追記:コメント頂いた。vcpkg にて、凄い勢いでビルドパッケージが構築されているので、Visual Studio 2015 以上を使う場合には、vcpkg を利用した方が良さそうです。
尚、Visual Studio を巡るバージョン情報は、@yumetodo さんにより更新されております(これ、凄い労力だな…)