古き悪しき全プロジェクト共通のVC++ディレクトリ的なSomethingを設定する方法
むか~し、むかし。Visual Studio 2008では設定>プロジェクトとソリューションからVC++ディレクトリの設定を行うことが出来た。
この設定では、全てのプロジェクトに共通した設定を書き込むことが出来、大変重宝しておった。
その一方で、色々な問題からVisual Studio 2010の頃には廃止された。
それ以来、プロジェクトに個別で設定するか、ユーザープロパティシートに書き込んで無理矢理に再現するかの2択になっている。
それで、先日Visual Studio 2017にアップデートした際に、再設定する必要があったので、書くネタにも困っていたところだし、メモとして残しておく。
ユーザプロパティシートは"%USERPROFILE%\Local\Microsoft\MSBuild\v4.0"にあるので、自分の環境に合わせて、Win32(x86)、Win64(x64)を編集する。
なお、今回紹介する設定方法はx86、x64共用なので、どちらでも同じ内容を書けば良い。
以下は実際の設定内容。
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets"> </ImportGroup> <PropertyGroup Label="UserMacros" /> <ItemDefinitionGroup /> <ItemGroup /> <PropertyGroup> <!--プラットフォーム名。x86かx64か--> <ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform> <ShortPlatform Condition="'$(Platform)' != 'Win32'">x64</ShortPlatform> <!--ツールセット名。v141がVisual Studio 2017--> <Toolset Condition="'$(PlatformToolset)' == 'v120'">vc12</Toolset> <Toolset Condition="'$(PlatformToolset)' == 'v140'">vc14</Toolset> <Toolset Condition="'$(PlatformToolset)' == 'v141'">vc14</Toolset> </PropertyGroup> <Choose> <When Condition="'$(PlatformToolset)' == 'v120' "> <PropertyGroup> <LibraryPath>D:\library\lib;$(LibraryPath)</LibraryPath> <IncludePath>D:\library\include;$(IncludePath)</IncludePath> </PropertyGroup> </When> <When Condition="'$(PlatformToolset)' == 'v140' AND '$(Platform)' == 'Win32'"> <PropertyGroup> <LibraryPath>D:\vs14library\lib;D:\vs14library\$(ShortPlatform)\$(Toolset)\lib;D:\vs14library\lib\vc_lib;$(LibraryPath)</LibraryPath> <IncludePath>D:\vs14library\include;$(IncludePath)</IncludePath> </PropertyGroup> </When> <When Condition="'$(PlatformToolset)' == 'v140' AND '$(Platform)' != 'Win32'"> <PropertyGroup> <LibraryPath>D:\vs14library\lib;D:\vs14library\$(ShortPlatform)\$(Toolset)\lib;D:\vs14library\lib\vc_x64_lib;$(LibraryPath)</LibraryPath> <IncludePath>D:\vs14library\include;$(IncludePath)</IncludePath> </PropertyGroup> </When> <When Condition="'$(PlatformToolset)' == 'v141' AND '$(Platform)' == 'Win32'"> <PropertyGroup> <LibraryPath>D:\vs14library\lib;D:\vs14library\$(ShortPlatform)\$(Toolset)\lib;D:\vs14library\lib\vc_lib;$(LibraryPath)</LibraryPath> <IncludePath>D:\vs14library\include;$(IncludePath)</IncludePath> </PropertyGroup> </When> <When Condition="'$(PlatformToolset)' == 'v141' AND '$(Platform)' != 'Win32'"> <PropertyGroup> <LibraryPath>D:\vs14library\lib;D:\vs14library\$(ShortPlatform)\$(Toolset)\lib;D:\vs14library\lib\vc_x64_lib;$(LibraryPath)</LibraryPath> <IncludePath>D:\vs14library\include;$(IncludePath)</IncludePath> </PropertyGroup> </When> </Choose> </Project>
以上なのでが、この設定ファイル、記述内容から何となくお察しかもしれないが、Visual Studio 2012の頃から使いまわしている。
そのため、中々にカオスなことになっているが悪しからず。
一応各部の解説をすると、Chooseタグが所謂if文にあたるタグで、WhenタグのCondition属性に式を設定する。このときif文内で使える変数はPropertyGroup内で宣言?した変数のみとなっている。
また、
つまるところ"D:\vs14library"とか"D:\library"とかなってる部分を自分の環境に合わせて変えれば良い。また、私の環境の場合、cmakeを使ってインストールしたライブラリをすべて1つのディレクトリに集約しているので1つないし、2、3個しかパスを足していないが、各ライブラリを別個のディレクトリにインストールしている場合、各ディレクトリを設定する必要がある。
ぶっちゃけ、Microsoftが公開している情報にたどり着けた試しがないせいか、実に5年間この説明があっているのかすらよくわからない。ただ、動いているという事実だけはあるので、まあいいかと捨て置いているので、誰か詳しい人いたらコメントください。
Visual Studio 2017を試してみた
はじめに
そもそもVisual Studio 2017の正式版がリリースされたのは3/7のことで、リリースノートによるとVisual C++の更新は軽微なもので、CMakeのサポートがメインになっている模様。
実際、ツールチェーンのバージョンも141とVisual C++14のマイナーアップデートにあたるらしい。
個人の開発だとC++しか使わない私としては、あまり代わり映えしない内容では有るが、一応実際に使った雑感について述べていく。
主要な新機能
概要
主要な新機能は下記の通り。
IDE全体で見ると結構変更点もあるんだなと思います。
あ、あくまでも、C++er視点なので、それ以外の変更点は山ほどあると思いますが悪しからず。
- Light Weight Solution Load
- CMakeのサポート
- Linuxを対象としたビルド
Light Weight Solution Load
Light Weight Solution Loadとは、その名の通り高速なSolution読み込み機能のことで、Solution読み込み時に全てのファイルの読み込みおよびInteli Senseによる解析を行わず、ユーザが開いたファイルなどを優先的に行うそうです。
これにより、これまで膨大な数のプロジェクトを読み込む際にかなり長い時間を待たされていたのですが、それがマシになる機能です。
実際に79プロジェクトから構成されるSolutionを読み込んで見ましたが、体感で3倍程でしょうか。
本当に早いです。
しかし、この機能はデフォルトではSolution毎に右クリックで表示されるメニューからEnableする必要があります。
これを全てのSolutionに対して有効にする場合、Tools>Options>Projects and Solutions>General の順に選択し、ページ下部のLightweight Solution loadのチェックボックスをチェックすれば良いそうです。
CMakeのサポート
「フォルダを開く」機能が追加されており、CMakeLists.txtを配置することで、Visual Studioが自動で他のディレクトリ(AppData配下に)を作ってCMakeを実行してくれるようになりました。
これにより、従来一度他のエディタでCMakeLists.txtを書いてから、CMakeを実行して、やっとVisual Studioからファイルの編集を行うことができる。というよう感じだったのが、Visual Studioのみで完結してCMakeを用いたプロジェクトを構築できるようになりました。
また、CMakeSettins.jsonという名前のファイルを配置することで、Visual Studioのバージョン、ビルド対象のアーキテクチャ毎に個別に詳細なオプションを設定することができるようなっています。
ただ、追加されたばかりの機能というだけあって、不満なところが結構あります。
まず、補完機能についてです。IDEなので補完機能も一応付いていますが、CMake tools for Visual Studioに比べても若干貧弱かなと思う所があります。
つぎに、CMakeの内部バージョンについてです。Visual Studioが呼び出すCMakeはVisual Studioが内包しているバイナリなのですがそのバージョンが3.6.0となっている点です。現在、CMakeの最新バージョンが3.8.0なので、それ比べると2バージョン前で若干古いですね。まあcontinue文がサポートされているバージョンなのでまだましかも知れませんが。
そして、最後にCMakeが実行されるタイミングについてです。CMakeが実行されるタイミングはフォルダ配下のCMakeに関係するファイル(CMakeLists.txtだけでなくソース中でincludeされているファイルも含まれている模様)を保存した際に毎回実行されるため、複数のCMakeに関係するファイルを変更する場合、毎回CMakeを実行する必要があって結構厄介です。
はじめてWebアプリケーションを作った話
はじめに
プログラミングを初めて早6年と3ヶ月。
これまでに、C++でアプリケーションを作ったことは数多くあれど、Webアプリケーションは作ったことがありませんでした。
ただ、某FEの試験を受けたり、QtからGoogleAPIをJavascript経由でバインディグしたりと色々やっていた影響でHTMLやJavascriptはそこそこ書けたのでぶっつけ本番でもなんとかなるかと思って実際に作ってみました。
が…思ってた異常に大変で躓いたところも多かったので、herokuを使ってPythonでWebアプリを作るまでに躓いたところを紹介したいと思います。
下記は実際に作ったアプリケーションへのリンクです
http://ppt-scripter.herokuapp.com/ppt-scripter.herokuapp.com
何つくったの
ざっくりと説明するとMicrosoftのPower Pointで作ったスライドからノートのみを抽出するアプリケーションです。
実は前回記事のGUIアプリケーションをやめて、Webアプリケーションにしてみました。
Webアプリの構成について
今回はherokuの公式が紹介しているdjangoで作るのではなく、もう少しlightにアプリを作れるらしいflaskを使って作ってみました。
また、pythonは2系ではなく、3系を使っています。
躓いたところ
以下は実際に躓いたところについて紹介していきます。
flaskの絡みはググれば出てくるので、多くのことで悩むことが無かったのですが、herokuの仕様が?すぎて辛かったです。
なお、私は初心者なので、もしその解決方法は不味いよってところがあったら教えてくれると嬉しいです。
Javascriptで躓いたところ。
Postでファイルをアップロードする時、input type="file"とDrag&DropAPIの両方を使う場合
Google Chromeの場合input type="file"にDrag&Dropしてやるとそのままアップロードできるのだけど、Edgeだとそんなことが無かったりする。
そのため、Drag&Dropでファイルを受け取る場合、JavascriptのDrag&DropAPIを使えば良いらしいのだけど、Formによる送信と共存させる方法が最初わからなかった。
ただ、まあ良くよく調べてみると簡単な話で、input type="file"の時とDrag&Drop APIで取得したファイルそれぞれを自前でnewしたFormDataに設定してやればいいそうです。
function uploadFiles(files) { filelist_dom.children().remove() var fd = new FormData() for(file of files) { fd.append('fileinputs', file, file.name) } $.ajax({ type:'POST', contentType: false, processData: false, url: '/convert', data: fd, dataType: 'json' }) } $('#file-upload').on('click', function(event) { event.preventDefault() $('#hidden-file-upload').click() }) $('#hidden-file-upload').change(function(event) { console.log('File upload via hidden input') event.preventDefault() uploadFiles(this.files) })
herokuで躓いた所
必要なファイルについて
前述の通り公式で紹介されているPythonによるWebアプリケーションはdjangoを用いたアプリケーションで、flaskを用いたアプリケーションではありません。
そのため、必要なファイルに若干の違いがあります。
結局Webアプリケーションを実行するまでに必要な最低限のファイルは下記の3つです。
- requirements.txt:必要なパッケージをリストするファイル
- runtime.txt:Pythonのバージョンを指定するファイル
- Procfile:Webアプリ実行のためのコマンドを書くファイル
requirements.txt
サーバサイドでPythonのパッケージをインストールする際に使われるファイル。
pipを使って出力すればいいらしい。
pip freeze > requirements.txt
Anacondaを使っているなら新しく環境を作成して必要なパッケージだけをインストールして実行すれば良いと思う。
runtime.txt
herokuではPython2系がデフォルトになっているので、Pythonのバージョンを指定してやる必要があります。下記リンクを見ると使用できるPythonのバージョンが書かれているので、今回はPython3.6.0を設定しました。
実際に設定ファイルに書いた内容は下記のとおりです。
python-3.6.0
Procfile
そもそもProcfileってなんぞや。という所から始まったのですが、どうやらProcfileというのは、foremanという1アプリケーションを複数プロセス管理するツールのためのファイルだそうです。
それで、ファイルフォーマットとしては、Webアプリケーションを実行する際のコマンドを列挙するファイルだそうで、下記のようなフォーマットで書くそうです。
<Process type>: <Command>
herokuでこのファイルを書く場合、Http通信のやりとりをするコマンドの
web: gunicorn <mainにあたるスクリプトファイル(拡張子なし)>:app --preload --log-file=-
ここで、ポイントなのが--preloadオプション。herokuのtutorialでは無くても動くようなことが書いてあったのですが、私の環境だと動かなかったので、追加しました。
おわりに
今回は、herokuでWebアプリケーションを作るまでに躓いたところをまとめました。
デザインとかはお察しですが、そのうちもう少しマシにしようと思っています。
PythonでGUIアプリケーションを作ろうとした話
はじめに
今回の話はタイトルどおり、Pythonを使ってGUIアプリケーションを作ろうとした話です。
これまでに、C++でアプリケーションを作ったことは数多くあれど、他の言語でアプリケーションを作った経験は少ないものです。
特に、スクリプト言語に絞ると無いと言っても過言ではないでしょう。
というのも、スクリプト言語というと、研究で何かしらの実験をして、その実験結果を整理するためのもの。
というイメージが強く、どうしても書捨てなイメージが強かったからです。
その一方で、C++でアプリケーションを作ると常に膨大な行数のソースコードとファイル数で、1つ作り上げるのに結構な時間を要するという至極一般的な問題がありました。
その上、実装中に「この書き方はできるだろ」と思ってたら実は駄目ですということがママあり*1、急遽設計を変更する羽目に会うことがあります。
そのため、あまりC++でアプリケーションを書ききったことがないという現実があります*2。
いくらなんでもそれは…と思い至り、少しでも完成率を上げるために、それならスクリプト言語で書けば良いんじゃねと結論に至りました。
GUIライブラリの選定
tkinter
言わずと知れた、Python付属のGUIライブラリ。
比較的簡単に使えるらしいのですが、どうも完成しても見た目があまり良くないそうで、ユーザー数が少ないそうです。
実際Googleで検索してもあまり込み入った話を書いたブログが見つからなかったので、実際少ないのでしょう。
というわけで、今回はボツ案で。
wxPython
wxWidgetsのPythonバインディング。
C++版に比べて使いやすいらしいのですが、wxWidgetsのWindows版はとにかくバグが多い*3上に、かなりお作法に厳しいので、あまり好きではありません。
というわけでボツですね。
PyQt5
Qt5のPythonバインディング。
文字列を標準のstring型ではなく、QString型をバインディングしたクラスを使ったりと結構面白いバインディングの仕方をしているライブラリです。
イベントの扱いにC++版と若干違いがあって、connectでSIGNALとSLOTというマクロを使って接続していたのですが、signal型のconnectを使ってslotを直接接続する感じになっています。
書いていてよくわからないので、例をあげます。実際にボタンのクリックイベントを使う時は下記のようにします。
button.clicked.connect(self.onClicked)
ただ、このライブラリ。
色々あって、ライセンスがLGPLではなく、GPLでしかライセンスされていません。
そのため、開発したアプリケーションにもGPLでライセンスをする必要があるため、注意が必要です。
そのため、今回はできればGPLでライセンスしたく無かったのでボツにしました。
アプリケーションのデプロイ
Pythonで作ったアプリケーションのデプロイについてです。
通常Pythonはスクリプト言語ですので、実行にインタプリタを必要とします。
しかし、それだと、自分が作ったアプリケーションをプログラマでないユーザに使ってもらおうとすると、ユーザにもPythonインタプリタをインストールすることを強いる必要があります。
それを回避するためのデプロイ用のアプリケーションを選定します。
今回作成したアプリケーションはPython3系で書いたので、Python3系で問題なく動作するアプリケーションが必要です。
下記で紹介しているアプリケーション全てpipからインストール可能なのでインストールも楽に済みます。
py2exe
多分一番有名なデプロイアプリケーション。
py2appなど、Windwos環境以外に向けた実装も用意されているため一応マルチプラットフォームで活用することが出来ます。
しかし、私の環境(Python3.5.2)ではどうもうまく動作せず。
実行中にエラーメッセージを吐いて異常終了してしまったので、うまくデプロイすることが出来ませんでした。
PyInstaller
py2exeでは、アプリケーションのデプロイに設定ファイルとしてのPythonスクリプトが必要なのですが、こいつはそれを必要としません。
ソースコードを解析して、必要なDLLを決定しているそうなのですが、その解析があまり賢くないため、過剰にDLLを集めてしまうそうです。
ただ、こいつの場合、entryポイントエラー(だったかな)DLL不足ではない謎の例外を吐いて、私の環境では上手く動いてくれなかったので、諦めました。
cx_Freeze
前2つと何が違うかと言われると「なんだろう?」ってなるくらいに、よく調べていません。
それはさておき、こいつは、py2exeと同様、設定ファイルを必要とするタイプですが、結構安定して動作するそうです。
それで実際に試してみると、一部DLLが不足してEXE起動時にDLL無いよって例外吐いて落ちてしまいました。
なんだか、進歩があったようなので、もう少し調べてみると、そういう場合はpackagesに含まれなかったライブラリを手動で足せば良いそうです。
実際に書いたsetup用のスクリプトは下記の通りです。
いまいちpackagesとincludesの違いはわかりませんが…とりあえず、こう書くそうです。
import sys from cx_Freeze import setup, Executable base = None if sys.platform == 'win32': base = 'Win32GUI' packages = ['lxml'] # これがデプロイされなかったライブラリ includes = ['PySide'] # デプロイ時に含めて欲しいライブラリ excludes = ['PyQt4'] # デプロイ時に含めて欲しくないライブラリ setup( name = 'Scripter', # アプリケーション名 version = '0.1', # アプリケーションのバージョン description = '', options = { 'build_exe' : {'includes':includes, 'excludes':excludes, 'packages': packages} }, executables = [Executable('main.py', base=base, icon='ICON.ico', targetName='Scripter.exe')] #出力するアプリケーション名やアイコンファイルを設定 )
インストーラの作成
インストーラの作成というとアプリケーションを本格的にユーザにデプロイする場合にしか必要としないため、あまり需要がない or そういうことをする人は自分で調べられるからなのかはわかりませんが、このあたりは日本語資料があまりないので、とりあえず書いておこうと思いました。
Install Shield
いわずと知れた、インストーラの代名詞的存在。いろんなソフトで見かけるかと思います。
しかし、こいつ、ライセンス条項が結構怪しいらしく、使用するPCをInstallShieldの開発元に監視されるらしく結構やばい。
というわけで、今回は候補から外します。
CNTKがガチでクソだったと思ってたらいつの間にかそうでも無くなってた話
はじめに
前回の記事を書いている最中に思い出したのだけれども、CNTKがガチでクソだった話を書こうと思ったらいつの間にかそうでも無くなってた話。
そもそもCNTKって
CNTKとはMicrosoft社が提供しているオープンソースなディープラーニングのライブラリで、マルチGPU性能が非常に高いことと、複数台のPCで実行可能なことを売りにしているディープラーニングライブラリです。
どれくらいマルチGPU性能が高いかと言うと、そもそもマルチGPUに対応していないTheanoは置いておいて、Tensor FlowやTorch、Caffeの倍近い性能を持つ他、2台のPCに各4基、合計8基のGPUを搭載して計算すると、他のライブラリよりも圧倒的に早いZEってライブラリです。
さらに、Microsoftが出しているだけあって、Windows対応を謳っている数少ないディープラーニングのライブラリでもあります。
CNTKのどこが糞だったん
これはあくまでもメジャーリリース当時の話です
私も上の説明を見た時はなんて素敵なライブラリなんだと、目を輝かせたものです。
ただ、それも幻影でした。
最初、Readmeとかよく読まず、とりあえず"cmake --build . --target Debug"とかでVisual Studioを起動せずに適当にビルドしようとしてたのですが、どうも成功せず。
とりあえず、slnファイルを開いてVisual Studioからビルドすかと思った矢先。なんとプロジェクト名に括弧書きで「Only Visual Studio 2013」(だったかな)と書かれていたのです。
それで、詳しく調べてみると、なんとこのCNTK、Visual Studio 2013にしか対応していないガチクソだったのです。
だったのですが…
今日、この記事を書こうとgithubを見てみると、最新のバージョンだとVisual Studio 2015に対応しているそうです。
という訳で一転して、CNTKは神ライブラリかもしれません。
また、暇になったら記事を書くかもしれませんが、、、いつに成ることやら
近況と生存報告と人気ページについて
先月からクソ忙しくて、録に更新してこなかったけどいい加減更新しようと思いいたった。のだけれども、どうも記事にできる内容がない。
いや、この三ヶ月、何もしてこなかった訳ではない。一応、研究成果の方はしっかり出して、それ相応の評価を頂戴した。
ただ、このブログに書けるような内容が、どれも進捗半端で紹介しかねるという状況だった。例えば、Webアプリ作った話とか、tensor flowのWindows版をインストールして使ってみた話とかCNTKがクソだった話とか、DLIBでDCGANを実装しようとして死にそうになってる話とか、もう色々あるんだけど……。
それで、とりあえず。はてブの編集ページへ飛ぼうとはてブのトップを開くと、右上のアカウント名のところに赤い通知が来ていた。
PV数が100を超えました
これを見た瞬間「はぁ?」となり、さらにPV数を確認して「……」となった。なんと、月間PVが100と言わず404になっていた。これまで、と言っても最後に更新したのは12月の話だが、その時は月間PV数なんて50を超えれば良いほうだった。それがほったらかしにした2ヶ月の間に何があったのかという話だ。
それで、記事の人気順を出して見るとその原因が何となく分かった。
総アクセス数に占める割合 | ページ名 |
23% | C++でDNNが使えないなんてあるわけないよ in Windows |
20% | CUDA 8.0がいつの間にかリリースされててVisual Studio 2015 Update 3でも使えるようになっていた話 |
11% | DLIBでCNNを使ってみた in Windows |
11% | DLIBのコンパイル For Debugビルド |
6% | DLIB with CUDAでCNNを使ってみた in Windows |
4% | Windowsでffmpegを使ってみた話 |
3% | /category/機械学習 |
2% | /category/dlib |
2% | GLEWをVisual Studio 2015とCMakeでビルドするときの注意点 |
2% | ブログトップ |
2% | OpenGLでズームを実装する方法 |
1% | GPGPUって色々あるけど結局どれがいいの |
1% | SFINAEやテンプレートの部分特殊化で気をつけたいこと |
1% | Visual Studio で拡張子のないC++ヘッダーをIntelli Senseで表示する方法 |
0% | PythonでDLLを使う時の話 |
0% | /category/深層学習 |
0% | Visual Studioユーザーに送るCMakeテクニック☆ (1) |
0% | cygwinでFindOpenCVするとエラーになる |
0% | Visual Studioユーザーに送るCMakeテクニック☆ (2) |
あー、ただのディープラーニングか。実際、「C++ DNN」とか「DLIB DNN」でGoogle検索を掛けると、ビックリするほど上位に出てくるから、やはりそういうことらしい。
とりあえず、今後もディープラーニングの話は書いていくつもりですのでよろしくお願いします。あ、それとCMake絡みの記事も読んでくれてもええんやで。
Visual Studioユーザーに送るCMakeテクニック☆ (3)
いやーこれでもう第三回ですよ。
なんとか自分で設定した週一更新のノルマを達成できそうですねー
それはさておき、今日は(1)と(2)の続きにあたるはなしで、(2)はCMakeListsを対象としたものでしたが、今回はそれ以外のヘッダーファイルやソースファイルを対象としたものです。
今回は少し長いので、gistに上げました。
かなり前に書いたためちょいちょいとお恥ずかしい部分(ぶっちゃけ汎用で作ればいいのになぜか専用品になってるあたりマジで…)もありますが、普通に使えるはずです。
下記は実際にこれを使い方です。実行したCMakeListsの保存されているディレクトリをルートとしてそのファイル内の全てのファイルについてフィルタリング&ファイルパスを取得できます。
使い方としては>|cmake|RecursiveGroupingWithFileSet(<探索するルートディレクトリ> <探索するディレクトリ一覧> <ヘッダーファイルの一覧が保存される変数名> <ソースファイルの一覧が保存される変数名>)|