目次: Linux
先日(2025年10月27日の日記参照)はGNU global + pygmentsでC/C++/Pythonのタグジャンプができる環境を整えましたが、微妙に動かない事態に遭遇したのでトラブルシューティングのメモを残しておきます。
Ubuntu 24.04は定義や参照へのジャンプができるため機能的には問題ありませんが、gtagsを実行する度に妙な警告が出ます。
$ gtags --gtagslabel=pygments
/usr/share/global/gtags/script/pygments_parser.py:92: SyntaxWarning: invalid escape sequence '\s'
tag = re.sub('\s+', '', tag) # remove newline and spaces
/usr/share/global/gtags/script/pygments_parser.py:161: SyntaxWarning: invalid escape sequence '\s'
match = re.search(r'(\S+)\s+(\d+)\s+' + re.escape(path) + '\s+(.*)$', line)
エラーの箇所を見るとglobalのヘルパースクリプト(/usr/share/global/gtags/script/pygments_parser.py)が間違っているっぽいので、下記のように修正すると警告が出なくなります。
--- pygments_parser.py.org 2025-10-26 22:48:13.811340349 +0900
+++ pygments_parser.py 2025-10-26 22:47:41.250646696 +0900
@@ -89,7 +89,7 @@
# we can assume index are delivered in ascending order
while self.lines_index[cur_line] <= index:
cur_line += 1
- tag = re.sub('\s+', '', tag) # remove newline and spaces
+ tag = re.sub(r'\s+', '', tag) # remove newline and spaces
if self.options.strip_punctuation:
tag = tag.strip(PUNCTUATION_CHARACTERS)
if tag:
@@ -158,7 +158,7 @@
line = self.child_stdout.readline()
if not line or line.startswith(TERMINATOR):
break
- match = re.search(r'(\S+)\s+(\d+)\s+' + re.escape(path) + '\s+(.*)$', line)
+ match = re.search(r'(\S+)\s+(\d+)\s+' + re.escape(path) + r'\s+(.*)$', line)
if match:
(tag, lnum, image) = match.groups()
if self.options.strip_punctuation:
この現象を確認した環境は以下の通りです。
$ global --version global (GNU Global) 6.6.11 Powered by Berkeley DB 1.85 and SQLite3 3.45.1. Copyright (c) 1996-2023 Tama Communications Corporation License GPLv3+: GNU GPL version 3 or later <http://www.gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ dpkg -l | grep global ii global 6.6.11-1 amd64 Source code search and browse tools $ pygmentize -V Pygments version 2.17.2, (c) 2006-2023 by Georg Brandl, Matthäus Chajdas and contributors. $ dpkg -l | grep pygme ii python3-pygments 2.17.2+dfsg-1 all syntax highlighting package written in Python 3
だいぶ長くなってしまいましたが、これでDebian/Ubuntuともに快適globalタグジャンプ生活が送れるはずです。やったぜ。
この記事にコメントする
目次: Linux
先日(2025年10月27日の日記参照)はGNU global + pygmentsでC/C++/Pythonのタグジャンプができる環境を整えましたが、微妙に動かない事態に遭遇したのでトラブルシューティングのメモを残しておきます。
DebianやUbuntuではpython-is-python3をインストールすると/usr/bin/pythonがpython3を指すようになります。しかし何か事情があってPythonをPython3に固定すると困る人はpython-is-python3をインストールしていないでしょう。そのときはglobalがこんなエラーを出します。
$ gtags --gtagslabel=pygments /usr/bin/env: 'python': No such file or directory gtags: unexpected EOF.
何かの理由で/usr/bin/pythonをpython3に固定しない場合、globalのヘルパースクリプト(/usr/share/global/gtags/script/pygments_parser.py)の先頭にあるpythonをpython3に書き換えればエラーが解消されます。かなり強引ですけど。
せっかちさんのために結論を先に書いておくと、Debian Testingではexuberant-ctagsだと動作しません。universal-ctagsに入れ替えてください。
Debian Testingではglobal, python3-pygments, exuberant-ctagsの組み合わせだと、C/Pythonともに定義個所と参照個所の検索ができません。参照個所へのタグジャンプができないのは致命的に使いにくくて困ります。
$ global -x cfunc_b
$ global -rx cfunc_b
$ global -x pyfunc_b
$ global -rx pyfunc_b
$ global -gx func
func 3 a.c int cfunc_b(int b);
func 5 a.c int cfunc_a(int a)
func 7 a.c return cfunc_b(a) + 1;
func 13 a.c printf("%d\n", cfunc_a(a));
func 1 a.py from b import pyfunc_b
func 3 a.py def pyfunc_a(a: int):
func 4 a.py return pyfunc_b(a) + 1
func 7 a.py print(f"{pyfunc_a(5)}")
func 1 b.c int cfunc_b(int b)
func 1 b.py def pyfunc_b(b: int):
この現象を確認した環境は以下の通りです。
$ gtags --version gtags (GNU Global) 6.6.14 Powered by Berkeley DB 1.85 and SQLite3 3.46.1. Copyright (c) 1996-2024 Tama Communications Corporation License GPLv3+: GNU GPL version 3 or later <http://www.gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ dpkg -l | grep global ii global 6.6.14-1.1 amd64 Source code search and browse tools $ pygmentize -V Pygments version 2.18.0, (c) 2006-2024 by Georg Brandl, Matthäus Chajdas and contributors. $ dpkg -l | grep pygments ii python3-pygments 2.18.0+dfsg-2 all syntax highlighting package written in Python 3
たぶん何かの設定間違いですよね。なんだろう?
Debian Testingでは最新版もしくはかなり新しいバージョンが採用されているはずですが「定義個所、参照個所が検知できない問題」が発生します。原因がさっぱりわからないのでglobalのソースコードを見ました。
# Debian Testingのglobalのコード
# global-6.6.14/plugin-factory/pygments_parser.py
def handle_requests(langmap, options):
# Update ctags's path from the configuration file
global UNIVERSAL_CTAGS
path = load_ctags_path()
if path != '':
UNIVERSAL_CTAGS = path
if UNIVERSAL_CTAGS != '' and UNIVERSAL_CTAGS != 'no':
pygments_parser = PygmentsParser(langmap, options)
try:
ctags_parser = CtagsParser(UNIVERSAL_CTAGS, options)
parser = MergingParser(ctags_parser, pygments_parser)
except Exception as e:
parser = pygments_parser
else:
parser = PygmentsParser(langmap, options)
#...
# (比較用)Ubuntu 24.04のglobalのコード
# global-6.6.11/plugin-factory/pygments_parser.py
def handle_requests(langmap, options):
# Update ctags's path from the configuration file
global EXUBERANT_CTAGS
path = load_ctags_path()
if path != '':
EXUBERANT_CTAGS = path
if EXUBERANT_CTAGS != '' and EXUBERANT_CTAGS != 'no':
pygments_parser = PygmentsParser(langmap, options)
try:
ctags_parser = CtagsParser(EXUBERANT_CTAGS, options)
parser = MergingParser(ctags_parser, pygments_parser)
except Exception as e:
parser = pygments_parser
else:
parser = PygmentsParser(langmap, options)
#...
コードからはDebian Testing側はuniversal-ctagsを参照していて、Ubuntu 24.04側はexuberant-ctagsを参照しているように見えます。公式サイト(https://www.gnu.org/software/global/)を改めて確認すると、"supports 25 languages by Pygments + Universal Ctags plug-in parser."と書いてありました。これは知らなかったです。
Internet Archiveで見ると2016年11月くらいにExuberant CtagsからUniversal Ctagsに表記が変わっていました。Release noteを見ると6.6.11(2023年11月リリース)でExuberant Ctagsがサポート外と記述されています。なぜ6.6.11を採用しているUbuntu 24.04でExuberant Ctagsが使えるのか謎が残りますが、深追いしてもあまり意味はないでしょう……。
$ sudo apt-get purge exuberant-ctags $ sudo apt-get install universal-ctags
話を戻すと、Debian Testingでは上記のようにexuberant-ctagsをアンインストールして、universal-ctagsをインストール(Debian系ならalternativesで切り替えても良いかも)すれば良いはずです。
#### Cの関数定義、参照個所を探す
$ global -x cfunc_b
cfunc_b 1 b.c int cfunc_b(int b)
$ global -rx cfunc_b
cfunc_b 3 a.c int cfunc_b(int b);
cfunc_b 7 a.c return cfunc_b(a) + 1;
#### Pythonの関数定義、参照個所を探す
$ global -x pyfunc_b
pyfunc_b 1 b.py def pyfunc_b(b: int):
$ global -rx pyfunc_b
pyfunc_b 1 a.py from b import pyfunc_b
pyfunc_b 4 a.py return pyfunc_b(a) + 1
#### grepモードでCもPythonも網羅的に探す
$ global -gx func
func 3 a.c int cfunc_b(int b);
func 5 a.c int cfunc_a(int a)
func 7 a.c return cfunc_b(a) + 1;
func 13 a.c printf("%d\n", cfunc_a(a));
func 1 a.py from b import pyfunc_b
func 3 a.py def pyfunc_a(a: int):
func 4 a.py return pyfunc_b(a) + 1
func 7 a.py print(f"{pyfunc_a(5)}")
func 1 b.c int cfunc_b(int b)
func 1 b.py def pyfunc_b(b: int):
改善されました。良かった良かった。次回はUbuntuです。
この記事にコメントする
目次: Linux
プログラムの関数、変数の定義元や参照先に一瞬で飛べるタグジャンプ機能を使っている人は多いと思います。私もGNU globalを使ってタグを生成、vim/gvimでタグジャンプを利用していて、とても便利です。
今まではC/C++のコードを読むことが多かったため、global単体で事足りました。最近はPythonのコードを読むことも増えまして、Pythonもタグジャンプできるように環境を整えることにしました。global単体ではPythonに対応していないので、プラグインとしてpygmentsを使います。exuberant-ctagsのインストールもお忘れなく。
もっとも単純なセットアップ方法&使い方はこんな感じです。
$ sudo apt-get install global python-is-python3 python3-pygments exuberant-ctags $ gtags --gtagslabel=pygments
下記のテストプログラムを使って、タグが正しく作成されたか確認しましょう。
//// a.c
#include <stdio.h>
int cfunc_b(int b);
int cfunc_a(int a)
{
return cfunc_b(a) + 1;
}
int main(int argc, char *argv[])
{
int a = 5;
printf("%d\n", cfunc_a(a));
return 0;
}
//// b.c
int cfunc_b(int b)
{
return b + 2;
}
#### a.py
from b import pyfunc_b
def pyfunc_a(a: int):
return pyfunc_b(a) + 1
if __name__ == "__main__":
print(f"{pyfunc_a(5)}")
#### b.py
def pyfunc_b(b: int):
return b + 2
テストとして基本的な機能3つを確かめます。
#### Cの関数定義、参照個所を探す
$ global -x cfunc_b
cfunc_b 1 b.c int cfunc_b(int b)
$ global -rx cfunc_b
cfunc_b 3 a.c int cfunc_b(int b);
cfunc_b 7 a.c return cfunc_b(a) + 1;
#### Pythonの関数定義、参照個所を探す
$ global -x pyfunc_b
pyfunc_b 1 b.py def pyfunc_b(b: int):
$ global -rx pyfunc_b
pyfunc_b 1 a.py from b import pyfunc_b
pyfunc_b 4 a.py return pyfunc_b(a) + 1
#### grepモードでCもPythonも網羅的に探す
$ global -gx func
func 3 a.c int cfunc_b(int b);
func 5 a.c int cfunc_a(int a)
func 7 a.c return cfunc_b(a) + 1;
func 13 a.c printf("%d\n", cfunc_a(a));
func 1 a.py from b import pyfunc_b
func 3 a.py def pyfunc_a(a: int):
func 4 a.py return pyfunc_b(a) + 1
func 7 a.py print(f"{pyfunc_a(5)}")
func 1 b.c int cfunc_b(int b)
func 1 b.py def pyfunc_b(b: int):
参照個所を探す機能は地味に便利なので、CでもPythonでも動作してくれるのはありがたいですね。
こんなあっさり動けば苦労はないですが、実はDebian TestingでもUbuntu 24.04でも微妙に動きませんでした。あまり使われていないのかもしれない。悲しい。次回はトラブルシューティング編です。
この記事にコメントする
目次: Linux
NTPで時刻を調整する方法は2つあって、ズレている時間をジワジワ合わせていく方法(slewモード)と一気に時間を変えて合わせる方法(stepモード)があります。ntpdはシステムに常駐してslewモードで時刻をジワジワ合わせて、標準時刻とズレないようにするのが期待だと思います。
またntpdateを使うときも、基本的にはslewモードが期待でしょう。ですがstepモードで時刻同期したい場合もあります。私の場合はRTCがないLinuxボードで、起動直後に時間がズレるので正しい時間に同期したいときなんてのがありました。stepモードで時刻同期する場合はntpdateにオプション-bを付けて実行します。
$ sudo ntpdate ntp.jst.mfeed.ad.jp 2025-10-22 xx:xx:xx.xxxxxx (+0900) +0.004300 +/- 0.002113 ntp.jst.mfeed.ad.jp 210.173.160.27 s2 no-leap $ sudo ntpdate -b ntp.jst.mfeed.ad.jp 2025-10-22 xx:xx:xx.xxxxxx (+0900) -0.000427 +/- 0.002179 ntp.jst.mfeed.ad.jp 210.173.160.87 s2 no-leap CLOCK: time stepped by -0.000427
上記の例のように1msもズレていないときは、何もオプションを指定しないとslewモードになります。一方で-bオプションを付ければ強制的にstepモードで時刻同期できます。
この記事にコメントする
目次: ALSA
未だにPipeWireの音切れがなくなりません。結論から書いておくと音切れは解決できませんでした。もう飽きました。今回はサーバー側PipeWire PulseAudioモジュールのレイテンシ調整をしました。
以前の日記(2025年10月11日の日記参照)で紹介したとおり、pipewireそのものにはリモート音声再生する機能はなくて、PulseAudioのプロトコルを受け付けるpipewire-pulseモジュールを使います。
モジュール(pipewire-pulse)の動作をstraceで追うと、設定ファイルは下記の3つが有効みたいです。
このうち/usr/share/pipewire/pipewire-pulse.confしか存在していなかったので、/usr/shareの設定ファイルを使います。
pulse.properties = {
#...
pulse.min.req = 64/48000
pulse.default.req = 128/48000
pulse.min.frag = 128/48000
pulse.default.frag = 96000/48000
pulse.default.tlength = 96000/48000
pulse.min.quantum = 64/48000
#...
}
とりあえずこんな感じに設定してみました。PipeWireの設定と何が違うんでしょうねえ。
S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME S 30 0 0 --- --- --- --- 0 Dummy-Driver S 31 0 0 --- --- --- --- 0 Freewheel-Driver S 47 0 0 --- --- --- --- 0 Midi-Bridge R 51 8192 48000 1.2ms 1.2ms 0.01 0.01 0 S24_32 2 48000 alsa_output.platform-es8316-s R 74 23744 48000 252.6us 692.1us 0.00 0.00 0 F32LE 2 48000 + mpv S 52 0 0 --- --- --- --- 0 alsa_input.platform-es8316-so S 53 0 0 --- --- --- --- 0 alsa_output.platform-hdmi0-so S 55 0 0 --- --- --- --- 0 alsa_output.platform-hdmi1-so S 56 0 0 --- --- --- --- 0 alsa_input.platform-hdmiin-so
PulseAudioモジュール側のバッファサイズが24000に近づきましたが、微妙に値が違います。まだ何か設定が要るんです??
しかし困ったことに、PipeWireのドキュメントは本当に意味がわからないです。読んでも「そんなこと聞いてないんだけど?」状態になります。設定項目のブロック構造もわからんし、何の設定項目があって、どの範囲の値が指定できて、どの値で何が起きるのか、全然分かりません。もうイヤ。
これ以上PipeWireに関してやる気が起きません……。PipeWireで何かトラブったら、PipeWireを即削除してPulseAudioを入れ直しをオススメします。
この記事にコメントする
目次: ALSA
PipeWireに変えてから音切れがなくなりません。PulseAudioのときも音切れはしてましたが、PipeWireになってから頻度が段違いに多いです。なぜー?結論から書いておくと、音切れは多少はマシになった気がしますが、完全には解決できていません。今回はサーバー側PipeWireのレイテンシ調整をしました。
PipeWireの設定ファイルはいくつかの場所を認識するみたいです。straceで追ってみると、
この3つが認識されるみたいで、私の環境では/usr/share/pipewire/pipewire.confのみ存在していたので、/usr/share以下にあるファイルを変更します。
設定変更前の状態を再掲しておきます。
S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME S 30 0 0 --- --- --- --- 0 Dummy-Driver S 31 0 0 --- --- --- --- 0 Freewheel-Driver S 47 0 0 --- --- --- --- 0 Midi-Bridge R 51 2048 48000 594.1us 320.5us 0.01 0.01 1 S24_32 2 48000 alsa_output.platform-es8316-s R 56 8192 48000 245.6us 253.7us 0.01 0.01 1 S32LE 2 48000 + mpv S 52 0 0 --- --- --- --- 0 alsa_input.platform-es8316-so S 53 0 0 --- --- --- --- 0 alsa_output.platform-hdmi0-so S 54 0 0 --- --- --- --- 0 alsa_output.platform-hdmi1-so S 55 0 0 --- --- --- --- 0 alsa_input.platform-hdmiin-so
RATEがサンプリング周波数で、QUANT(※)がバッファサイズのようです。ALSAデバイス側は2048サンプル、PulseAudioモジュール(mpvの話し相手)は8192サンプルです。mpvはpulse-buffer=500を指定したので、500msつまり24000サンプルになるはずですが、なぜか8192です。
ローカル再生なら2桁msのバッファサイズ量で問題ないし、むしろレイテンシがデカすぎなくらいですが、リモート再生だと音がブチブチ切れまくって聞くに堪えません。仕方ないのでバッファを増量する設定を追加します。context.propertiesにある「default.clock.*」系の設定が効くっぽいです。
context.properties = {
#...
default.clock.rate = 48000
default.clock.allowed-rates = [ 48000 ]
default.clock.quantum = 64
default.clock.min-quantum = 32
default.clock.max-quantum = 8192
default.clock.quantum-limit = 48000
こんな感じにしてみました。大事なのはmax-quantum(デフォルト値2048)とquantum-limit(デフォルト値8192)でした。max-quantumはALSAデバイス側に使われるようで、quantum-limitはmpvから指定された値の上限になるみたいです。mpvから長いレイテンシを指定しても、quantum-limitまで切り詰められ意味がなかったのです。
S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME S 30 0 0 --- --- --- --- 0 Dummy-Driver S 31 0 0 --- --- --- --- 0 Freewheel-Driver S 47 0 0 --- --- --- --- 0 Midi-Bridge R 51 8192 48000 508.0us 1.2ms 0.00 0.01 160 S24_32 2 48000 alsa_output.platform-es8316-s R 54 22080 48000 233.0us 181.7us 0.00 0.00 0 F32LE 2 48000 + mpv S 52 0 0 --- --- --- --- 0 alsa_input.platform-es8316-so S 53 0 0 --- --- --- --- 0 alsa_output.platform-hdmi0-so S 55 0 0 --- --- --- --- 0 alsa_output.platform-hdmi1-so S 56 0 0 --- --- --- --- 0 alsa_input.platform-hdmiin-so
設定変更後、ALSAデバイス側は8192サンプル、PulseAudioモジュール(mpvの話し相手)は22080サンプルになりました。mpvはpulse-buffer=500を指定しているので、24000になってほしいんですけど。なぜこんな微妙な値になるの……??
この記事にコメントする
| < | 2025 | > | ||||
| << | < | 10 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | - | 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 | - |
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: