読者です 読者をやめる 読者になる 読者になる

空飛ぶ気まぐれ雑記帳

主に趣味とかプログラミングについて扱います。

Visual Studioユーザーに送るCMakeテクニック☆ (3)

いやーこれでもう第三回ですよ。
なんとか自分で設定した週一更新のノルマを達成できそうですねー

それはさておき、今日は(1)と(2)の続きにあたるはなしで、(2)はCMakeListsを対象としたものでしたが、今回はそれ以外のヘッダーファイルやソースファイルを対象としたものです。
今回は少し長いので、gistに上げました。

gist.github.com

かなり前に書いたためちょいちょいとお恥ずかしい部分(ぶっちゃけ汎用で作ればいいのになぜか専用品になってるあたりマジで…)もありますが、普通に使えるはずです。
下記は実際にこれを使い方です。実行したCMakeListsの保存されているディレクトリをルートとしてそのファイル内の全てのファイルについてフィルタリング&ファイルパスを取得できます。

使い方としては>|cmake|RecursiveGroupingWithFileSet(<探索するルートディレクトリ> <探索するディレクトリ一覧> <ヘッダーファイルの一覧が保存される変数名> <ソースファイルの一覧が保存される変数名>)|

なんかデスマってたからレムちーのボクセルキャラクターを描いてみた

学会前のセルフハンディキャッピングの一環としてなぜかボクセルキャラクターを作りたくなったのでRe:ゼロのレムを作ってみました。
参考は下記、3つのサイトです。

CHARACTER|TVアニメ『Re:ゼロから始める異世界生活』オフィシャルサイト
ultimei.hatenablog.com
github.dev7.jp

一番上は参考画像。まあRe:ゼロのアニメ版公式サイトですね。
それから、真ん中は基本的な書き方、一番下はテンプレートを拝借しました。

それで、実際に書いていて一箇所だけ詰まったのが、パレットの設定です。

パレットからいらない色を選択して、左下のHSVというペーン内で設定することができるのですが、
HSVというのはスライダーの部分のパラメータだけで、スライダーの下のテキストボックスはRGBなので、手打ちで色を入力する際は注意が必要です。

f:id:elda27:20161211005903p:plain

それ以外は特に詰まること無くスイスイと書くことができました。
もともと絵心がない上に製作時間が1時間なので出来具合はお察しください。

正面
f:id:elda27:20161211011721p:plain

頭上
f:id:elda27:20161211012821p:plain

側面
f:id:elda27:20161211012818p:plain

背面
f:id:elda27:20161211012824p:plain

パンツは未実装
f:id:elda27:20161211012815p:plain

ガラス調
f:id:elda27:20161211011728p:plain

メタル調
f:id:elda27:20161211011731p:plain

それでも、自分で作ったからか何となく愛着が湧いちゃって。もうね、どれ位かって言うとこんな記事を作っちゃうくらいですよね。

とりあえず、今後も作るかは分からないけれども、課題としてはもう少し凝ってみたいので、より大きなサイズのボクセルモデルを作ってみたいですね。

追記:
投稿してからすぐに気づいたのだけれども、なんかメイド服なのにしっくりこないなと思っていたら、カチューシャ(?)の存在を忘れていたので慌てて付け足しました。

f:id:elda27:20161211014917p:plain

Visual Studioユーザーに送るCMakeテクニック☆ (2)

Visual Studioユーザーに送るCMakeテクニック☆ 、第二回目です。
今回は、昨日の記事で説明したフィルタリング機能を使って、CMakeファイルをVisualStudioから簡単に見えるようにしようって話です。
具体的にはどういうことかと言うと下記のように各ディレクトリに配置されているCMakeListsと*.cmakeファイルをディレクトリ構造をフィルタ名としたCustomプロジェクトを作成します。

f:id:elda27:20161130000643p:plain

下記が実際のソースコードです。

FILE(GLOB_RECURSE CMAKE_LIST_FILES CMakeLists.txt *.cmake)

FOREACH(file ${CMAKE_LIST_FILES})
  FOREACH(dir ${CMAKE_CURRENT_LIST_DIR})
    FILE(RELATIVE_PATH relative ${CMAKE_CURRENT_LIST_DIR} ${file})
    
    STRING(REGEX MATCHALL "[^/]+" filters "${relative}")
    LIST(LENGTH filters output_length)
    MATH(EXPR iteration "${output_length} - 2")
    
    IF(${iteration} LESS 0)
      continue()
    ENDIF()
    
    SET(group_string "")
    FOREACH(i RANGE 0 ${iteration})
      LIST(GET filters ${i} g)    
      set(group_string "${group_string}\\${g}")
      #MESSAGE(${i},${output_length}:${g})
    ENDFOREACH()
    SOURCE_GROUP("${group_string}" FILES ${file})
  ENDFOREACH()
ENDFOREACH()

ADD_CUSTOM_TARGET(CMakeLists SOURCES ${CMAKE_LIST_FILES})
<||

Visual Studioユーザーに送るCMakeテクニック☆ (1)

はじめに

今月忙しすぎてブログの更新が滞っていたので、暫くごまかしのためにCMakeのテクニックを紹介します。
なお、未だに忙しくて録に記事が書ける状態ではないので記事は分割してますが、悪しからず。

決して当初掲げていた週一更新の分を一気に放出しようとしているわけではありません

それはさておき、今日紹介するのはVisual Studioが有するフィルタリング機能をCMakeから利用するにはどうすれば良いのか?
という話です。

フィルタリング機能って

Visual Studioでプロジェクトを右クリックしてでてくるポップアップメニューの Add > New Filterで出てくるアレです。
デフォルトでも、Source filesやHeader files(日本語版だとソースファイルとヘッダーファイルかな?)というものが設定されているかと思います。

このフィルタリング機能ですが、これがないとソースファイルの数が100近くなると非常に見づらくなるので、どっぷりとVisual Studioを使っている方は間違いなく利用しているかと思います。

これをCMakeを使ってソリューションファイルを生成するとデフォルトのSource filesやHeader filesのフィルタリングすらないため、非常に不便ですよね。

フィルタリングを有効にする

下記コマンドを実行すればフィルタリングが有効になります。
なお、デフォルトでSource filesとHeader filesが設定され、振り分けられます(久しくデフォルトの挙動を確認していないので不安ですが…)。

SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON) 

もし、これをONにしない場合、以下で説明している設定をしても反映されないので注意しましょう

ソースファイルをフィルタリングしたいとき

ソースファイルをフィルタに分類する場合、下記コマンドを実行すればOKです。

SOURCE_GROUP("任意のフィルタ名" FILES <ソースコードのファイルパス> ...)

なお、もしフィルタをネストする場合、例えば Source files > hoge > huga > hage.cpp のような階層構造を持たせたい場合、フィルタ文字列をバックスラッシュ2つ(文字列内の場合バックスラッシュをエスケープする必要がある?)並べる必要があります。

SOURCE_GROUP("Source files\\hoge\\huga" FILES hage.cpp)

のようになります。

プロジェクトをフィルタリングしたいとき

プロジェクトの場合ソースコードとは違う方法でフィルタリングを行います(フィルタリングのフォーマットは同じ)

SET_TARGET_PROPERTIES(<プロジェクト名(ターゲット名)> PROPERTIES FOLDER "任意のフィルタ名")

ここで注意しなければならないのが、ターゲットを対象としてフィルタリングするため、add_executable or add_library or add_custam_target etc... でターゲットを生成した後に呼び出す必要があるという所。

おわりに

ざっくりとCMakeを使ったフィルタリングの使い方を説明しました。
次回以降も個人的に知ってて便利だな―と思ったCMakeの使い方を説明していくつもりです。

なお、全五回くらいになる予定していますそんなにネタがあるか微妙ですが

Visual Studio で拡張子のないC++ヘッダーをIntelli Senseで表示する方法

Qt+CMakeを使いつつVisual Studioを使っていると拡張なしのヘッダーファイルをインクルードしたい時がある(実際には拡張し有りのヘッダーファイルをインクルードすれば事足りるので特に問題にはならないが…)。
その場合、なぜかIntelli Senseでは標準ライブラリ以外の拡張子無しのヘッダーファイルが候補として表示されることはない。

本当になぜかは分からないが…

それはさておき、解決方法。
Tools > Options... から設定画面を開く。
それから TextEditor > FileExtension から拡張子に関する設定画面を開く。
その後,「Editor:」と「Map extensionless files to:」をMicrosoft Visual C++に変更して、チェックボタンをチェックしてからOKボタンをクリックして設定完了。

f:id:elda27:20161129232257p:plain

Windowsでffmpegを使ってみた話

はじめに

ffmpegを使ってみた話ですが、あくまでもC++から使ってみようっていう話。
ffmpegバイナリを使うって話はググれば山ほど出てくるんだけど、Cのライブラリを使うって言う話はあまり出てこなかったので、備忘録を兼ねて。

そもそも、どうしてffmpegを使おうと思い至ったかと言いますと、OpenCVのVideoCaptureってコーデックが揃った外部のffmpegを指定してもフレームのシークや動画情報の取得が上手く行かない場合が多く、そもそもコーデックに対応してないなんて場合もあって微妙に使いづらいという問題があります。(汎用的な機構でいろんな動画フォーマットを開けるというだけで十分便利なのですがね)

それで、ffmpegを直接使えば多少の手間はかかれど、そういう問題はないだろうと思い、実際に試してみました。

準備

いつも通り、Windows環境での話しかしませんので、MacLinuxの人はパッケージマネージャーで適当に準備してください。
それで、Windows環境の場合ですが一からffmpegをビルドするのは大量のコーデックをビルドする必要があって、かなり骨が折れるので下記からダウンロードしてきましょう。
32bit、64bit、好きな方を選んで、SharedとDevの両方のパッケージをダウンロードしましょう。なぜかはわかりませんが、Devを選択してダウンロードしてくるとリンクするシンボルが含まれたlibファイルはあるのにdllがないのでSharedパッケージに含まれるdllを併せて利用します。

Builds - Zeranoe FFmpeg

テストコード

下記のサンプルコードを改変してC++で使えるようにしました。ただ、それだけだと面白みが無いので、フレームのシークをできるようにてみました。(正しく動いているとは言ってない)
ffmpeg tutorial

ポイントは、ffmpegのヘッダーを extern "C" で括ってやることぐらいですかね。
ただ、このコード。たまにシーク出来ないことがあるので、おそらくどこか間違ってるんでしょうね。おいおい修正します。

gist.github.com

cygwinでFindOpenCVするとエラーになる

やんごとなき事情により、cygwincygwinでcmakeを使う必要がでてきたのだけれども、FindPackageでapt-cygでインストールしたOpenCVを探すとエラーが出た。

以下は実際のエラー出力

CMake Error at /lib/cmake/opencv/OpenCVModules.cmake:124 (message):
The imported target "opencv_core" references the file

"//lib/libopencv_core.dll.a"

but this file does not exist. Possible reasons include:

* The file was deleted, renamed, or moved to another location.

* An install or uninstall procedure did not complete successfully.

* The installation package was faulty and contained

"/lib/cmake/opencv/OpenCVModules.cmake"

but not all the files it references.

Call Stack (most recent call first):
/lib/cmake/opencv/OpenCVConfig.cmake:71 (include)
util/CMakeLists.txt:5 (find_package)

それで、その原因となるコードを追っかけると原因はOpenCVModules-relwithdebinfo.cmakeにあった。
以下はその1行目から17行目を抜粋したコード

#----------------------------------------------------------------
# Generated CMake target import file for configuration "RelWithDebInfo".
#----------------------------------------------------------------

# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)

# Import target "opencv_core" for configuration "RelWithDebInfo"
set_property(TARGET opencv_core APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
set_target_properties(opencv_core PROPERTIES
  IMPORTED_IMPLIB_RELWITHDEBINFO "${_IMPORT_PREFIX}/lib/libopencv_core.dll.a"
  IMPORTED_LINK_INTERFACE_LIBRARIES_RELWITHDEBINFO ""
  IMPORTED_LOCATION_RELWITHDEBINFO "${_IMPORT_PREFIX}/bin/cygopencv_core-2.4.dll"
  )

list(APPEND _IMPORT_CHECK_TARGETS opencv_core )
list(APPEND _IMPORT_CHECK_FILES_FOR_opencv_core "${_IMPORT_PREFIX}/lib/libopencv_core.dll.a" "${_IMPORT_PREFIX}/bin/cygopencv_core-2.4.dll" )

つまるところ/lib/opencv_core.dll.aに探したいライブラリがあるんだけど、_IMPORT_PREFIXが/の場合//lib/opencv_core.dll.aに成ってしまっているというのが問題です。本来Linuxでは/をいくつ重ねても許容されますが、cygwinでは//がWindows環境における\\と同一の意味として解釈されるため、libとういう名前のサーバー無いためエラーとなります。

というわけで、このコードの8行目に以下のコードを追加して末尾の/を削除するように変更。

string(REPLACE "/" ";" _IMPORT_PREFIX_TEMP ${_IMPORT_PREFIX})
list(LENGTH _IMPORT_PREFIX_TEMP _IMPORT_PREFIX_LENGTH)
SET(_IMPORT_ITERATION_COUNT 2)
while(${_IMPORT_ITERATION_COUNT} LESS ${_IMPORT_PREFIX_LENGTH})
  math(EXPR _INSERT_POSITION "${_IMPORT_ITERATION_COUNT} - 2")
  list(INSERT ${_INSERT_POSITION} ${_IMPORT_ITERATION_COUNT} "/")
  math(EXPR _IMPORT_ITERATION_COUNT "${_IMPORT_ITERATION_COUNT}+1")
endwhile()

string(CONCAT _IMPORT_PREFIX ${_IMPORT_PREFIX_TEMP})

unset(_INSERT_POSITION)
unset(_IMPORT_PREFIX_TEMP)
unset(_IMPORT_PREFIX_LENGTH)
unset(_IMPORT_ITERATION_COUNT)

結構アドホックな気がするけど、急ぎの案件だったのでとりあえず、これで解消しました。
同じ症状に陥って、他にこうしたらなんかCMake通ったよみたいな人いたら教えて欲しいです。