ffmpeg configure 研究1-命令行参数的分析

发布于:2025-02-15 ⋅ 阅读:(36) ⋅ 点赞:(0)

author: hjjdebug
date: 2025年 02月 14日 星期五 17:16:12 CST
description: ffmpeg configure 研究1
./configure 命令行参数的分析



详细分析了 ffmpeg 下执行
./configure --enable-libx264
libx264 is gpl and --enable-gpl is not specified.
程序退出的过程

如果说在命令行上有 --enable-libx264 而没有 --enable-gpl 就退出,
用c 写也就寥寥几句,
libx264_enable=false,gpl_enable=fale;
for(int i=0;i<argc;i++)
{
if(strcmp(arg[i],“–enable-libx264”)0) libx264_enable=true;
if(strcmp(arg[i],“–enable-gpl”)0) gpl_enable=true;
}
if(libx264_enable
true && gpl_enable
false) exit(1)

如果用bash 又应该怎么写呢?
如果只是实现上边的功能,bash 也可以写的很简单, 但在configure 文件中就不是那样写了.
而是有一个复杂的架构,
为什么?因为它要支持一些复杂的功能.

所以该博客就是来了解这个简单的功能是如何在复杂的架构上实现的.
让我们能窥斑见豹. 别被它庞大的架构吓唬注了.
这些是bash编程最基本的东西, 就从此开始吧.

1 configure 对命令行参数的分析,在4019行

for opt do
因为 opt 后面没有 in 参数, 实际上就是 in “ @ " , 代码处于顶层 , @",代码处于顶层, @",代码处于顶层,@就是命令行参数,此时
$opt = --enable-libx264
case 语句会匹配到4087行
–enable-?|–disable-?)
eval ( e c h o " (echo " (echo"opt” | sed ‘s/–/action=/;s/-/ option=/;s/-/_/g’)
if is_in $option $COMPONENT_LIST; then
test $action = disable && action=unset
eval $action $$(toupper ${option%s})_LIST
elif is_in $option $CMDLINE_SELECT; then
$action $option
else
die_unknown $opt
fi

bash 在每次执行命令前要进行8大变换. 其是也是很简单的.
大括号扩展 {} , 把形如 {1…5} 扩展为 1 2 3 4 5
波浪线扩展 ~ , 把~扩展为你的家目录
变量扩展 , 简单方式就是 {} , 简单方式就是 ,简单方式就是var样式, 就是变量引用和变量替换
算术扩展 $(()) , 数学运算在这里进行
命令替换 $()或 ``, 这里可以调用命令,先执行命令
分词分割 IFS , 按照空格,tab,回车来分割成单词
路径扩展 * ? [] , 把*展开匹配任意字符,?匹配0或1个字符,[]匹配指定字符
引号去除 , 去除其中的双引号,单引号

把该行信息都收拾一遍叫扫描,然后再交给bash去执行命令,
eval ( e c h o " (echo " (echo"opt" | sed ‘s/–/action=/;s/-/ option=/;s/-//g’)
eval 语句会进行2次扫描. 即扩展了一遍还要再扩展一遍,所以有$$(…)之类的写法
执行第一遍扫描,进行变量扩展
eval $(echo --enable-libx264 | sed 's/–/action=/;s/-/ option=/;s/-/
/g’)
,进行命令替换
eval action=enable option=libx264

运行eval命令,执行第二遍扫描,(此例第一遍已经扩展干净了,第二遍没有要改变的.)
action=enable option=libx264
这条语句交给bash执行,就是定义了2个变量,并赋值.
elif is_in $option $CMDLINE_SELECT; then
$action o p t i o n l i b x 264 在 option libx264 在 optionlibx264CMDLINE_SELECT 中被发现,会执行 enable libx264 函数


1.1 函数名称: is_in

输入参数: 列表
输出参数:
返回值: 0(成功), 1(失败,假)
描述: 把第一个参数作为值, 依次与后续参数做比较,如果想等,返回成功,全部不成功,返回失败.


is_in(){
value=$1 # 第一个参数为value
shift
for var in KaTeX parse error: Expected 'EOF', got '#' at position 7: *; do #̲ 后续参数与value相比
[ $var = KaTeX parse error: Expected 'EOF', got '&' at position 9: value ] &̲& return 0 # 相同…value被扩展为libx264, $CMDLINE_SELECT 被扩展为一堆字符串, 其中包含libx264, 所以其返回为成功.
$action $option 被扩展为:
enable libx264


1.2. 函数名称: enable

输入参数: 列表
输出参数: 无
返回值: 无
描述: 把参数都做为变量,其值设置为"yes"


enable(){
set_all yes $*
}
执行结果, 把libx264 设置为了 yes, 等价与 libx264=yes


1.3. 函数名称: set_all

输入参数: 列表
输出参数: 无
返回值: 无
描述: 把第一个参数作为value, 其余的参数都作为变量用$value赋值


set_all(){
value=$1 # 第一个参数为value,
shift # 移除第一个参数
for var in $*; do
eval v a r = var= var=value # 其余参数都设置为$value
done
}

注意: 调试时打印pr value 是没有意义的, pr $value才是对变量的引用.

2 执行退出判断的关键代码:

map “die_license_disabled gpl” $EXTERNAL_LIBRARY_GPL_LIST $EXTERNAL_LIBRARY_GPLV3_LIST
$EXTERNAL_LIBRARY_GPL_LIST 变量在1721行有定义,包括libx264,libx265及其它模块
该语句功能. 检查一系列模块,如果enable 了模块而没有enable gpl, 就退出.


2.1. 函数名称: map

输入参数: 列表
输出参数: 无
描述: 把第一个参数作为命令, 后续参数依次作为$v参数,来执行第一条命令


map(){
m=$1 # 把die_license_disabled gpl 赋值给m
shift
for v; do eval $m; done # 把后面的参数依次送给v, 执行 $m,即执行die_license_disabled gpl 函数
}


2.2 函数名称: die_license_disabled

输入参数: 函数调用参数 1 , 全局参数 1, 全局参数 1,全局参数v
输出参数: 无
功能描述: 判断第1个参数(对应“gpl”,“nonfree”)是否enabled,如果已经enabled,则正常退出;
否则判断$v 参数是否 enabled, 如果为真则打印错误信息并退出(die 函数)
注意: 不满足条件时会退出程序.


die_license_disabled() {
enabled $1 || { enabled KaTeX parse error: Expected 'EOF', got '&' at position 3: v &̲& die "v is $1 and --enable-$1 is not specified."; }
}
命令可以作为map 的第一个参数. 该命令接受的参数是$1 和 $v


2.3 函数名称 enabled()

输入参数: 一个参数
输出参数: 无
返回值: 0或1
描述: 对参数$1 判断其值是否是"yes"


enabled(){
test “${1#!}” = “$1” && op=“=” || op=“!=” # 该句设置op为等号或不等号
eval test “x$${1#!}” $op “xyes” # 运行test返回真值或假值.
}
${1#!}是$1变量去除从开始到!止部分,$1无!则不会去除任何东西.

3. 小测试代码

为了对enabled() 函数,die() 及颜色设置有更深入理解,我写了如下测试函数

$ cat 1.sh
#!/bin/bash
enabled(){
    test "${1#!}" = "$1" && op="=" || op="!=" # 根据第一个参数是否首字符为!为op赋值=或者!=
    eval test "x\$${1#!}" $op "xyes"  # 测试变量的值是否为yes
}
if test -t 1 && which tput >/dev/null 2>&1; then
    ncolors=$(tput colors)
    if test -n "$ncolors" && test $ncolors -ge 8; then
        bold_color=$(tput bold)
		warn_color=$(tput setaf 3)    # 设置前景色为黄(3)
		error_color=$(tput setaf 1)   # 设置前景色为红(1) , set attr foregroud
        reset_color=$(tput sgr0)      # 恢复颜色, set groud 0
    fi
    # 72 used instead of 80 since that's the default of pr
    ncols=$(tput cols)
fi
: ${ncols:=72}  # :就是空操作, 退出总是成功 ${var:=}, 如果ncols 没有值,就给72,否则保持不变

logfile="1.log"
log(){
    echo "$@" >> $logfile
}
die(){
    log "$@"
    echo "$error_color$bold_color$@$reset_color" # 设置红色,加重的颜色,显示$@ 然后颜色再恢复
}

abc=yes
enabled abc && echo "abc enabled" || echo "abc not enabled"
enabled abb && echo "abb enabled" || echo "abb not enabled"

die "I hope this is red"

4.执行结果 $ ./1.sh

abc enabled
abb not enabled
I hope this is red

5.小结:

bash脚本命令. 就是一个命令的集合体.
你在命令行下所做的操作, 用bash脚本都可以完成.
而且除了执行命令外,bash 还支持变量,支持函数.
函数也可以看成命令的集合.
所以bash脚本就是不断的执行命令.
命令需要参数,参数不断的通过8大扩展提供出来.
参数可能会赋值给变量
函数可能会对输入变量进行运算.变换,调用命令,创建输出变量
引入变量可以简化人机的接口,使少敲几个字符就给计算机说明白了.
函数完成特定的功能.
正如命令也是完成特定的功能.
常在bash下工作的人, 用脚本编程简化维护等工作也是很自然的了.


网站公告

今日签到

点亮在社区的每一天
去签到