在前面的博文MinGW下编译nginx源码中,有介绍到使用compiledb
工具在MinGW
环境中生成compile_commands.json
,以为compiledb
是捕获的make
时的输出,而nginx
生成时控制台是有输出编译时的命令行信息的,笔者之前编译过ffmpeg
的源码,它不是完全输出编译时的命令行信息,而只是简单的输出CC XXX.o
这样的信息,那compiledb
能否正常生成compile_commands.json
呢?为此笔者尝试了一下。
笔者编译开源源码时,为了不污染源码,一般喜欢单独创建一个build
目录来编译,这也是开源界所提倡的。所以笔者在MinGW下编译ffmpeg源码时也是如此。要编译ffmpeg
的源码,与大多数开源代码一样,需要先运行configure
脚本,生成Makefile
,再调用make
来编译。
在ffmpeg
源码下建立build
目录,并在其下执行:
$ ../configure --prefix=
$ compiledb make -j8
看是否会生成compile_commands.json
,结果却生成不了。我以为真是从我们看到的屏幕信息中捕获的信息,于是我让它在编译时把命令显示出来:
$ compiledb make -j8 V=1
make的命令行参数V=1
定义变量V
让它显示详细信息,参见源码ffbuild/common.mak
:
从Makefile
规则中可以看到所有编译规则都是调用的COMPILE
宏,再执行的相应的命令,如果没定义变量V
则重写了BRIEF
中所列的所有命令,调用printf
以命令 目标
的格式显示,再执行相应的命令。
可以使用remake
工具进行调试查看。在MinGW
下使用命令:
$ pacman -S remake
安装remake。
在build
目录使用命令:
$ remake -X
调试Makefile
,再使用expand COMPILE_C
查看展开后的变量COMPILE_C
回到主题,使用
$ compiledb make -j8 V=1
依旧不能生成compile_commands.json
,为此我还调试了compiledb
源码,发现实际是解析到了结果,但是最后因为找不到实际的源文件,所以未生成compile_commands.json
。MinGW
下编译ffmpeg
源码时,在build
目录下使用../configure
生成的Makefile
,是使用的绝对路径,而不是相对路径,MinGW
下的Windows
目录的绝对路径表示与Windows
的本身表示的不一样,Windows本身的路径如:H:\OpenSource\ffmpeg\build
,在MinGW
下是/h/OpenSource/ffmpeg/build
。
从前面ffbuild/common.mak
中的COMPILE
宏中可以知道编译源文件时是使用了SRC_PATH
和SRC_LINK
变量,使用remake
的p SRC_PATH
命令查看位置,在ffbuild/config.mak:15
。
ffbuild/config.mak
是由configure
程序生成的,那需要在configure
源码去找生成ffbuild/config.mak
时的写入代码:
cat > ffbuild/config.mak <<EOF
# Automatically generated by configure - do not modify!
ifndef FFMPEG_CONFIG_MAK
FFMPEG_CONFIG_MAK=1
FFMPEG_CONFIGURATION=$FFMPEG_CONFIGURATION
prefix=$prefix
LIBDIR=\$(DESTDIR)$libdir
SHLIBDIR=\$(DESTDIR)$shlibdir
INCDIR=\$(DESTDIR)$incdir
BINDIR=\$(DESTDIR)$bindir
DATADIR=\$(DESTDIR)$datadir
DOCDIR=\$(DESTDIR)$docdir
MANDIR=\$(DESTDIR)$mandir
PKGCONFIGDIR=\$(DESTDIR)$pkgconfigdir
INSTALL_NAME_DIR=$install_name_dir
SRC_PATH=$source_path
SRC_LINK=$source_link
8106行开始写入,8121行使用了$source_path
变量
查找设置$source_path
变量的地方,4248行开始:
原来它只假定了源码的根目录使用configure
命令和把根目录作为src
目录使用configure
命令两种方式的相对路径,其它都是使用的绝对路径。为了支持在子目录build
下使用configure
命令,添加:
elif test -f ../configure; then
source_path=..
再次运行
$ ../configure --prefix=
$ compiledb make -j8
这回正常生成compile_commands.json
了。
当然了,如果只是想生成compile_commands.json
,也可以直接在根目录运行:
$ ./configure --prefix=
$ compiledb -n make -j8
即可。这样就可以使用VSCode打开项目,在代码中正常跳转了!
总结下来,compiledb
其实是可以正常生成compile_commands.json
的,并且它并不是以我们在屏幕上看到的输出来生成compile_commands.json
的。感兴趣的读者可以自行去看它的python源码。
如果对你有帮助,欢迎点赞收藏!