コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2021年6月24日 >>> 2021年6月11日
link もっと後

2021年6月24日

プログラムからLLVMを実行する その2 - プリプロセス編

目次: LLVM

準備が終わりましたらClang/LLVMをプログラムから呼びましょう。

LLVMでプリプロセスだけを実行するプログラム

int main(int argc, char *argv[])
{
	bool success;

	clang::CompilerInstance CI;
	clang::CompilerInvocation &build = CI.getInvocation();

	// 引数の配列を作成する
	std::vector<const char*> vec_args;
	vec_args.push_back("-I/usr/include/c++/10");
	vec_args.push_back("-I/usr/include/x86_64-linux-gnu/c++/10");
	vec_args.push_back("-I/usr/include/c++/10/backward");
	vec_args.push_back("-I/usr/lib/llvm-11/lib/clang/11.0.1/include");
	vec_args.push_back("-I/usr/include/x86_64-linux-gnu");
	vec_args.push_back("-I/usr/include");
	vec_args.push_back("-I/path/to/llvm-project/_install/include");

	// エラーメッセージを出力するために使われるクラス
	llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagID = new clang::DiagnosticIDs();
	llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagOpts = new clang::DiagnosticOptions();
	clang::TextDiagnosticBuffer *diagBuffer = new clang::TextDiagnosticBuffer();
	clang::DiagnosticsEngine diags(diagID, diagOpts, diagBuffer);
	CI.createDiagnostics(diagBuffer, false);

	// コンパイラ呼び出し用のインスタンスを作成する
	llvm::ArrayRef<const char*> ref_args(vec_args.data(), vec_args.data() + vec_args.size());
	success = clang::CompilerInvocation::CreateFromArgs(build, ref_args, diags);

	// コンパイラフロントエンドのオプション設定
	//   入力ソースコード: test.cpp
	//   出力ソースコード: test.preproc.cpp
	const char *source_file = "test.cpp";
	const char *preproc_file = "test.preproc.cpp";
	clang::FrontendOptions &fe   = build.getFrontendOpts();
	clang::InputKind ik          = clang::InputKind(clang::Language::CXX);
	clang::FrontendInputFile fif = clang::FrontendInputFile(source_file, ik);

	fe.Inputs.clear();
	fe.Inputs.push_back(fif);
	fe.OutputFile.assign(preproc_file);

	// プリプロセスのオプション設定
	//   言語: C++11
	clang::PreprocessorOptions &po = build.getPreprocessorOpts();
	clang::LangOptions *la         = build.getLangOpts();
	llvm::Triple triple            = llvm::Triple();
	build.setLangDefaults(*la, ik, triple, po.Includes, clang::LangStandard::lang_cxx11);

	// 下記のようにオプションの一部だけ変えることもできる
	//la->CPlusPlus = true;
	//la->CPlusPlus11 = true;

	// プリプロセスのオプション
	//   コメント、定義済みマクロなどは出力しない
	clang::PreprocessorOutputOptions &poo = build.getPreprocessorOutputOpts();
	poo.ShowCPP = true;
	poo.ShowComments = false;
	poo.ShowLineMarkers = false;
	poo.ShowMacros = false;
	poo.ShowMacroComments = false;
	poo.RewriteIncludes = false;

	// プリプロセス実行(失敗したらエラーログを出力する)
	clang::PrintPreprocessedAction Preprocess;
	success = CI.ExecuteAction(Preprocess);
	if (!success) {
		get_build_log(diagBuffer, (CI.hasSourceManager()) ? &CI.getSourceManager() : nullptr);
	}
}

残念ながらこの呼び出し方が正解とは断言できません。探した限りではどう呼び出すべきか書かれたドキュメントも見当たりませんでした。上記の例はpoclを参考にしており、大きな間違いはないはずですが……。何かやらかしていたら教えていただけると嬉しいです。

動作確認はLLVM 12で行いました。他のバージョンだとAPIの引数などが変わっているので、ビルドすら通らないと思います。LLVMの困ったところですね……。

インクルードパスの調べ方

上記のサンプルでは引数で -Iオプションを使ってインクルードパスを指定します。インクルードパスは頑張ってヘッダファイルがある場所を調べても良いですが、おそらく同じ名前のヘッダが複数の場所にあって混乱すると思いますから、PCで動作しているClang++ から拝借するのが簡単です。

clangのインクルードパスを調べる
$ clang++ test.cpp -v

Debian clang version 11.0.1-2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10

...

#include "..." search starts here:
#include <...> search starts here:
 /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10
 /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10
 /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward
 /usr/lib/llvm-11/lib/clang/11.0.1/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

...

いろいろなメッセージが出力されますが、インクルードパスは "search starts here:" の辺りに書かれています。出力は特に捻りはなくディレクトリ名そのものですので、頭に -Iを足せばオプションの出来上がりです。

実行

プリプロセスを実行します。テスト用のプログラムは下記のとおりです。

テスト用のプログラム

#include <iostream>

int main(int argc, char *argv[])
{
	// This is comment
	std::cout << "Hello, world!!" << std::endl;
}

プリプロセス実行
$ make

$ ./clang_test

ファイル名などは完全に決め打ちのため引数は必要ありません。実行に成功するとプリプロセス後のソースコードtest.preproc.cppが作成されているはずです。

プリプロセス後のソースコード

namespace std
{
  typedef long unsigned int size_t;
  typedef long int ptrdiff_t;


  typedef decltype(nullptr) nullptr_t;

}

...

  static ios_base::Init __ioinit;


}

int main(int argc, char *argv[])
{

 std::cout << "Hello, world!!" << std::endl;
}

私の環境で実行したところ27,000行くらいあるファイルになりました。たった1つしかヘッダをincludeしてないのに凄まじい行数に展開されます。コメントは消えていますが、オプションを変更すれば残すこともできます。PreprocessorOutputOptionsのShowComments = trueにすると残ります。

プリプロセス後のソースコードをビルド&実行
$ g++ test.preproc.cpp

$ ./a.out
Hello, world!!

プリプロセス後のソースコードをg++ などに渡すとコンパイル可能なので、おそらく変な出力にはなっていないでしょう。

編集者:すずき(2023/09/24 09:16)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年6月23日

プログラムからLLVMを実行する その1 - 準備編

目次: LLVM

LLVMやClangは実行する方法が2つあります。1つ目はみなさまお馴染みのコマンドラインから実行する方法で、2つ目はプログラムからClangのライブラリを通して実行する方法です。

特に後者のプログラムから実行する方法はGCCでは真似できませんから、LLVMならではの機能と言えるでしょう。ただ、ちょっとインタフェースが不安定というか、バージョンによってちょいちょい変わって動かなくなるようで、そこは玉に瑕ですね。

LLVMビルド&インストール

Clang/LLVMをプログラムから実行するにはいくつか準備が必要です。大まかに分けるとLLVMのビルド&インストールと、ヘッダおよびライブラリパスの指定です。

ビルドは以前もチャレンジしました(2019年3月26日の日記参照)。基本的にはcmakeとmake(またはninja)です。それは変わりませんが、いくつか追加したいオプションがあるので再掲します。

LLVMのビルドオプション
$ cmake \
  -G Ninja \
  ../llvm \
  -DCMAKE_INSTALL_PREFIX=`pwd`/../_install \
  -DCMAKE_C_COMPILER=clang \
  -DCMAKE_CXX_COMPILER=clang++ \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DBUILD_SHARED_LIBS=ON \
  -DLLVM_ENABLE_ASSERTIONS=ON \
  -DLLVM_TARGETS_TO_BUILD="X86;RISCV;NVPTX" \
  -DLLVM_USE_LINKER=lld \
  -DLLVM_BUILD_LLVM_DYLIB=OFF \
  -DLLVM_LINK_LLVM_DYLIB=OFF \
  -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;compiler-rt;debuginfo-tests;libc;libclc;libcxx;libcxxabi;libunwind;lld;lldb"

ざっくり意図を説明すると下記のとおりです。オプションの正確な意味についてはLLVM公式ドキュメント(Build LLVM with CMake - LLVM 12 documentation 参照)を見てください。

CMAKE_INSTALL_PREFIX
インストール先を指定します。システムに既にインストールされているLLVMを破壊しないよう、ビルドディレクトリの隣の _installディレクトリにインストールする指定です。
LLVM_TARGETS_TO_BUILD
以前(2019年3月27日の日記参照)も使いましたが、特定ターゲットのみをビルドするオプションで、ビルド時間の短縮に繋がります。2つ以上指定する場合はセミコロンで繋ぎましょう。例ではx86とRISC-V向けにしていますが、お好きなアーキテクチャを足してください。
LLVM_BUILD_LLVM_DYLIB
全てのライブラリを1つのライブラリlibLLVM.soに集約するオプションです。興味があればこのオプションのON/OFFにより後述するllvm-configの出力がどう変化するか確認すると面白いかもしれません。
LLVM_ENABLE_PROJECTS
LLVMはLLVM以外にも多彩なツールを持っています。どのツールをビルドするか選択するオプションです。全ては必要ないですが少なくともclangは後で必要になります。例では全部入りにしています。

CMakeの実行が成功したら、ninja installを呼びましょう。インストールまで進むはずです。

Makefileの作成

ヘッダインクルードパスの指定、ライブラリパスの指定のためにMakefileを書きます。パスの細かい値について心配する必要はありません。llvm-configというツールが用意されており、ほぼ全て自動的に用意してくれます。Makefileの一例を示すと、

テスト用のMakefile

LLVM_CONFIG_PATH  = /path/to/llvm-project/_install/bin
LLVM_CONFIG       = $(LLVM_CONFIG_PATH)/llvm-config --link-shared

CPPFLAGS = $(shell $(LLVM_CONFIG) --cppflags)
CFLAGS   = $(shell $(LLVM_CONFIG) --cflags) -g
CXXFLAGS = $(shell $(LLVM_CONFIG) --cxxflags) -g
LDFLAGS  = $(shell $(LLVM_CONFIG) --ldflags) 
LIBS     = -lclang-cpp $(LLVM_CONFIG) --libs --system-libs engine)

clang_test: main.o
	$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(APP) $< $(LIBS)

基本的にはllvm-config --xxxflagsとするとオプションに指定すべき文字列が出力されますから、素直に各種FLAGSに渡すだけです。もちろん何かオプションを追加するのも自由です。例では -gを足しています。

LIBSのところがちょっと格好悪いのは、llvm-configでlibclang-cppにリンクするような方法が見当たらなかったからです。良い方法をご存知の方は教えていただけると嬉しいです。

これで準備完了です。続きは次回に。

編集者:すずき(2023/09/24 09:16)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年6月21日

mplayer, mpvでイコライザーを使う

目次: ALSA

いつもわからなくなるのでメモしておきます。mplayerにてイコライザーを使う方法です。最近はmpvと呼ぶんですかね?

コマンドはmpvを使いますが、実はイコライザー機能はffmpegの一部であるlibavfilter.soに頼っています(avfilterのドキュメントへのリンク)。この構造は一見しただけではわかりにくく、ヘルプを探すときに非常に難儀しました。設定方法も独特でいつも書き方がわからなくなります。

イコライザーはsuperequalizerという名前です(superequalizerのドキュメントへのリンク)。18バンド指定できます。各バンドがどの周波数帯に対応するかはドキュメントを見てください。

mpvでavfilterのsuperequalizerを設定する例
$ mpv --no-video --af=volume=0.8,superequalizer=1.2:1.5:1.5:1.2:1.2:1:1:1:1:1:1:1:1:1:1:1:1:1 a.mp4

     Video --vid=1 (*) (h264 480x360 6.000fps)
 (+) Audio --aid=1 (*) (aac 2ch 44100Hz)
AO: [pulse] 44100Hz stereo 2ch float
A: 00:00:01 / 00:04:40 (0%) Cache: 278s/9MB

上記の例では、映像を出さない(--no-video)、音割れ防止の為にvolumeで8割くらいに音を下げる、superequalizerの18バンドを全て設定しています。superequalizer=1b=1.2:2b=1.5のようにすると特定のバンドだけ設定変更できます。便利な方を使ってください。

mpvのバージョン
$ mpv --version

mpv 0.32.0 Copyright © 2000-2020 mpv/MPlayer/mplayer2 projects
 built on UNKNOWN
ffmpeg library versions:
   libavutil       56.51.100
   libavcodec      58.91.100
   libavformat     58.45.100
   libswscale      5.7.100
   libavfilter     7.85.100
   libswresample   3.7.100
ffmpeg version: 4.3.2-0+deb11u2

動作確認に使ったmpvのバージョンも記録しておきます。なぜならffmpegやmpvはたまにインタフェースが激変するので、将来的に同じ方法が通用しなくなる可能性が高いからです。使用しているディストリビューションはDebian Testingです、今はDebian 11相当みたいですね。

なぜかbuilt on UNKNOWNになっていて若干気になりますけど、特に害なさそうだから良いのかな……。

編集者:すずき(2023/01/23 14:10)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年6月20日

読書一生分が93万円?

目次: マンガ紹介

書籍通販のhontoがこんなキャンペーンをやっています。


honto読書一生分プレゼントキャンペーン

このキャンペーン画像を見たときの率直な感想としては、どんな人間を想定したら、読書一生分がたった93万円に収まるのか?でした。マンガしか読んでない自分でさえ100万じゃ10年も持ちません。

1世帯あたり読書にいくら使う?

思い込みで文句を言うのは良くないなと思って、統計データを見ました。総務省統計局 - 読書に関する支出(2018年)によると、1世帯、読書の支出が年間10,628円(電子書籍含まず)です。電子書籍を含む値段で考えたとしても、さほど変わりません。電子書籍を最も購入している30代(世帯主の年齢)でも1,736円で、読書支出は12,000円程度だからです。

世帯の読書支出10,628円x日本人の平均寿命84年 = 892,752円となり、hontoのキャンペーン金額と大体同じくらいになります。あながち間違った数値でもなかった、ということですね。

1人あたり読書にいくら使う?

先程のデータを見ていて何が驚いたって、1世帯で1年間たった1万円しか本を買わないことです。この時点で少ないなと思うんですけど……。1世帯には複数人が生活していますので、1人あたりの支出も計算してみます。

世帯の平均人数はe-Statで調べることができます。平均世帯人員、年次別(平成27年国民生活基礎調査 世帯票 報告書掲載 年次推移 表番号7)を見ると、2015年で1世帯平均2.49人です。

世帯あたり読書の支出は1年10,628円(書籍7,478円、雑誌3,150円)割ることの、日本の平均世帯人数2.49人(減少傾向)ですから、1人あたり1年で4,268円(書籍3,003円、雑誌1,265円)です。さらに少なくなりました。

例えば、週刊少年ジャンプ(定価270円x 50冊 = 13,500円)をもれなく買うだけで3倍以上の支出になります。普段全く本は買わない、くらいじゃないと1年4,268円は厳しいです。世間の生活が想像できません……。

編集者:すずき(2024/11/02 13:22)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年6月18日

RISC-V - まとめリンク

目次: RISC-V

関係の深いまとめリンク。

SiFive社ボードの話、CoreMarkの話のまとめ。

その他の話のまとめ。

編集者:すずき(2024/08/28 23:29)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年6月17日

Raspberry Pi 3のオーディオ その8 - シミュレーションと実測値の差(解決編)

目次: Raspberry Pi

Raspberry Pi 3のAudio Outの最後の謎がわかりました。

  • PWMのDuty比100%を維持したときに減衰する速度が異なります。

その6(2021年5月12日の日記参照)にてRaspberry Pi 3の回路図が間違っているのでは?と疑っていましたが、違いました。ケーブルに入っている抵抗のせいでした。

抵抗入りケーブル

今まで測定に使用していたオーディオケーブルにはプラグ内に抵抗が入っています。そもそもなんでこんなの買ったんだろ……?プラグの見た目からはわかりませんので、テスターで各端子間の抵抗を計測した結果は下記のとおりです。

ミニLミニRミニGRCA LRCA GRCA RRCA G
ミニL --- 294 14746.7k 14746.7k 147
ミニR --- 14747.0k 14746.4k 147
ミニG ---47.0k 047.0k 0
RCA L ---47.0k94.0k47.0k
RCA G ---47.0k 0
RCA R ---47.0k
RCA G ---

測定結果から想定される回路図です。左がミニジャック側、右がRCAプラグ側です。


想定される抵抗入りケーブルの回路図

再度シミュレーション

この結果を踏まえてシミュレーションすると実測値とほぼ一致しました。


Audio Out回路のシミュレーション結果(125Hz矩形波を入力に設定)ケーブルの抵抗を考慮


Audio Out回路の実測値(黄色Audio Out、水色PWM信号125Hz矩形波)

気づいてみれば何とも初歩的なミスでしたが、ケーブルは0Ωと思い込んで見落としました。他人(RasPiの回路図)を疑う前に自分を疑えという良い教訓ですね〜。

編集者:すずき(2021/06/19 01:09)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2021年6月24日 >>> 2021年6月11日
link もっと後

管理用メニュー

link 記事を新規作成

<2021>
<<<06>>>
--12345
6789101112
13141516171819
20212223242526
27282930---

最近のコメント20件

  • link 21年9月20日
    すずきさん (11/19 01:04)
    「It was my pleasure.」
  • link 21年9月20日
    whtさん (11/17 23:41)
    「This blog solves my ...」
  • link 24年10月1日
    すずきさん (10/06 03:41)
    「xrdpで十分動作しているので、Wayl...」
  • link 24年10月1日
    hdkさん (10/03 19:05)
    「GNOMEをお使いでしたら今はWayla...」
  • link 24年10月1日
    すずきさん (10/03 10:12)
    「私は逆にVNCサーバーに繋ぐ使い方をした...」
  • link 24年10月1日
    hdkさん (10/03 08:30)
    「おー、面白いですね。xrdpはすでに立ち...」
  • link 14年6月13日
    2048player...さん (09/26 01:04)
    「最後に、この式を出すのに紙4枚(A4)も...」
  • link 14年6月13日
    2048playerさん (09/26 01:00)
    「今のところ最も簡略化した式です。\n--...」
  • link 14年6月13日
    2048playerさん (09/16 01:00)
    「返信ありがとうございます。\nコメントが...」
  • link 14年6月13日
    すずきさん (09/12 21:19)
    「コメントありがとうございます。同じ結果に...」
  • link 14年6月13日
    2048playerさん (09/08 17:30)
    「私も2048の最高スコアを求めたのですが...」
  • link 14年6月13日
    2048さん (09/08 17:16)
    「私も2048の最高スコアを求めたのですが...」
  • link 14年6月13日
    2048playerさん (09/08 16:10)
    「私も2048の最高スコアを求めたのですが...」
  • link 02年8月4日
    lxbfYeaaさん (07/12 10:11)
    「555」
  • link 24年6月17日
    すずきさん (06/23 00:12)
    「ありがとうございます。バルコニーではない...」
  • link 24年6月17日
    hdkさん (06/22 22:08)
    「GPSの最初の同期を取る時は見晴らしのい...」
  • link 24年5月16日
    すずきさん (05/21 11:41)
    「あー、確かにdpkg-reconfigu...」
  • link 24年5月16日
    hdkさん (05/21 08:55)
    「システム全体のlocale設定はDebi...」
  • link 24年5月17日
    すずきさん (05/20 13:16)
    「そうですねえ、普通はStandardなの...」
  • link 24年5月17日
    hdkさん (05/19 07:45)
    「なるほど、そういうことなんですね。Exc...」

最近の記事3件

  • link 23年4月10日
    すずき (11/15 23:48)
    「[Linux - まとめリンク] 目次: Linux関係の深いまとめリンク。目次: RISC-V目次: ROCK64/ROCK...」
  • link 24年11月6日
    すずき (11/15 23:47)
    「[Ubuntu 24.04 LTS on ThinkPad X1 Carbon Gen 12] 目次: Linux会社ではTh...」
  • link 24年11月11日
    すずき (11/15 23:26)
    「[Pythonのテストフレームワーク] 目次: Python最近Pythonを触ることが増えたのでテストについて調べようと思い...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 11/19 01:04