openwrt/scripts/kconfig.pl 理解

本文介绍 OpenWRT 中 kconfig.pl 脚本的功能及使用方法,包括配置文件合并、冲突处理规则和各种操作符的具体实现,有助于深入理解 OpenWRT 的内核配置流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

openwrt/scripts/kconfig.pl 理解

目的

理解 openwrt/scripts/kconfig.pl ,了解.config 的生成

开始

一般的编译内核

.config 是由 make xxx_defconfig 生成的

在OpenWrt 中则更复杂些

涉及的文件有

  • /openwrt/target/linux/generic/config-4.14
  • /openwrt/target/linux/sunxi/config-4.14
  • /openwrt/target/linux/sunxi/cortexa7/config-default

需要理清上述文件的关系,摘取编译时的输出如下:

/openwrt/scripts/kconfig.pl  + + /openwrt/target/linux/generic/config-4.14 /openwrt/target/linux/sunxi/config-4.14 /openwrt/target/linux/sunxi/cortexa7/config-default > /openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_glibc_eabi/linux-sunxi_cortexa7/linux-4.14.63/.config.target
awk '/^(#[[:space:]]+)?CONFIG_KERNEL/{sub("CONFIG_KERNEL_","CONFIG_");print}' /openwrt/.config >> /openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_glibc_eabi/linux-sunxi_cortexa7/linux-4.14.63/.config.target

为理解 openwrt/scripts/kconfig.pl 的用途,创建 A.config B.config C.config

$ cat A.config 
CONFIG_A=y
$ cat B.config 
CONFIG_B=y
$ cat C.config 
CONFIG_C=y
$ /openwrt/scripts/kconfig.pl + + A.config B.config C.config 
CONFIG_A=y
CONFIG_B=y
CONFIG_C=y

可见 /openwrt/scripts/kconfig.pl + + 作用是将三个文件的配置拼成一个。

那当三个文件存在冲突时,输出会怎么样呢。

我们修改 C.config

$ vi C.config 
CONFIG_C=y
CONFIG_B=m

输出如下:

$ /openwrt/scripts/kconfig.pl + + A.config B.config C.config 
CONFIG_A=y
CONFIG_B=m
CONFIG_C=y

可见C.config 会覆盖 B.config

再验证 B 是否覆盖 A

$ vi B.config 
CONFIG_B=y
CONFIG_A=m
$ /openwrt/scripts/kconfig.pl + + A.config B.config C.config 
CONFIG_A=m
CONFIG_B=y
CONFIG_C=y

确实是 B > A

总结:当存在冲突时,优先顺序是 C > B > A 。

kconfig.pl 其它用法

$ cat A.config 
CONFIG_A=y
CONFIG_B=y
CONFIG_ALL=y
$ cat B.config 
CONFIG_B=y
CONFIG_A=m

减法 -

$ /openwrt/scripts/kconfig.pl -  A.config B.config
CONFIG_ALL=y

与 &

$ /openwrt/scripts/kconfig.pl \&  A.config B.config 
CONFIG_B=y

diff >

$ /openwrt/scripts/kconfig.pl \>  A.config B.config 
CONFIG_A=m

m+

$ /openwrt/scripts/kconfig.pl m+ A.config B.config
CONFIG_A=y
CONFIG_ALL=y
CONFIG_B=y

源码

#!/usr/bin/env perl
# 
# Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

use warnings;
use strict;

my @arg;
my $PREFIX = "CONFIG_";

sub set_config($$$$) {
        my $config = shift;
        my $idx = shift;
        my $newval = shift;
        my $mod_plus = shift;

        if (!defined($config->{$idx}) or !$mod_plus or
            $config->{$idx} eq '#undef' or $newval eq 'y') {
                $config->{$idx} = $newval;
        }
}

sub load_config($$) {
        my $file = shift;
        my $mod_plus = shift;
        my %config;

        open FILE, "$file" or die "can't open file '$file'";
        while (<FILE>) {
                chomp;
                /^$PREFIX(.+?)=(.+)/ and do {
                        set_config(\%config, $1, $2, $mod_plus);
                        next;
                };
                /^# $PREFIX(.+?) is not set/ and do {
                        set_config(\%config, $1, "#undef", $mod_plus);
                        next;
                };
                /^#/ and next;
                /^(.+)$/ and warn "WARNING: can't parse line: $1\n";
        }
        return \%config;
}


sub config_and($$) {
        my $cfg1 = shift;
        my $cfg2 = shift;
        my %config;

        foreach my $config (keys %$cfg1) {
                my $val1 = $cfg1->{$config};
                my $val2 = $cfg2->{$config};
                $val2 and ($val1 eq $val2) and do {
                        $config{$config} = $val1;
                };
        }
        return \%config;
}


sub config_add($$$) {
        my $cfg1 = shift;
        my $cfg2 = shift;
        my $mod_plus = shift;
        my %config;

        for ($cfg1, $cfg2) {
                my %cfg = %$_;

                foreach my $config (keys %cfg) {
                        if ($mod_plus and $config{$config}) {
                                next if $config{$config} eq "y";
                                next if $cfg{$config} eq '#undef';
                        }
                        $config{$config} = $cfg{$config};
                }
        }
        return \%config;
}

sub config_diff($$$) {
        my $cfg1 = shift;
        my $cfg2 = shift;
        my $new_only = shift;
        my %config;

        foreach my $config (keys %$cfg2) {
                if (!defined($cfg1->{$config}) or $cfg1->{$config} ne $cfg2->{$config}) {
                        next if $new_only and !defined($cfg1->{$config}) and $cfg2->{$config} eq '#undef';
                        $config{$config} = $cfg2->{$config};
                }
        }
        return \%config
}

sub config_sub($$) {
        my $cfg1 = shift;
        my $cfg2 = shift;
        my %config = %{$cfg1};

        foreach my $config (keys %$cfg2) {
                delete $config{$config};
        }
        return \%config;
}

sub print_cfgline($$) {
        my $name = shift;
        my $val = shift;
        if ($val eq '#undef' or $val eq 'n') {
                print "# $PREFIX$name is not set\n";
        } else {
                print "$PREFIX$name=$val\n";
        }
}


sub dump_config($) {
        my $cfg = shift;
        die "argument error in dump_config" unless ($cfg);
        my %config = %$cfg;
        foreach my $config (sort keys %config) {
                print_cfgline($config, $config{$config});
        }
}

sub parse_expr {
        my $pos = shift;
        my $mod_plus = shift;
        my $arg = $arg[$$pos++];

        die "Parse error" if (!$arg);

        if ($arg eq '&') {
                my $arg1 = parse_expr($pos);
                my $arg2 = parse_expr($pos);
                return config_and($arg1, $arg2);
        } elsif ($arg =~ /^\+/) {
                my $arg1 = parse_expr($pos);
                my $arg2 = parse_expr($pos);
                return config_add($arg1, $arg2, 0);
        } elsif ($arg =~ /^m\+/) {
                my $arg1 = parse_expr($pos);
                my $arg2 = parse_expr($pos, 1);
                return config_add($arg1, $arg2, 1);
        } elsif ($arg eq '>') {
                my $arg1 = parse_expr($pos);
                my $arg2 = parse_expr($pos);
                return config_diff($arg1, $arg2, 0);
        } elsif ($arg eq '>+') {
                my $arg1 = parse_expr($pos);
                my $arg2 = parse_expr($pos);
                return config_diff($arg1, $arg2, 1);
        } elsif ($arg eq '-') {
                my $arg1 = parse_expr($pos);
                my $arg2 = parse_expr($pos);
                return config_sub($arg1, $arg2);
        } else {
                return load_config($arg, $mod_plus);
        }
}

while (@ARGV > 0 and $ARGV[0] =~ /^-\w+$/) {
        my $cmd = shift @ARGV;
        if ($cmd =~ /^-n$/) {
                $PREFIX = "";
        } elsif ($cmd =~ /^-p$/) {
                $PREFIX = shift @ARGV;
        } else {
                die "Invalid option: $cmd\n";
        }
}
@arg = @ARGV;

my $pos = 0;
dump_config(parse_expr(\$pos));
die "Parse error" if ($arg[$pos]);
<think>好的,我现在需要帮助用户解决OpenWrt构建过程中因`find`命令导致的“execdir insecure path variable”错误。首先,我得理解这个错误的原因。根据用户提到的错误信息,可能与环境变量中的路径不安全有关。通常,`find`命令的`-execdir`选项要求当前目录在PATH环境变量中,否则会报错,这是为了防止潜在的安全风险。 接下来,我应该回忆一下OpenWrt的构建过程。根据引用[3],构建过程中会下载源代码到`dl`目录,然后在`build_dir/<arch>`中进行编译。可能在这个过程中调用了`find`命令,而某些环境变量设置不当导致了问题。 用户提供的引用[1]提到了安装命令的宏定义,可能与文件复制有关,但不确定是否直接相关。引用[2]关于路由设置的配置可能不相关。所以重点应放在构建过程中的环境变量和路径设置上。 解决方案方面,可能需要调整PATH变量,确保当前目录(.)不被包含,或者修改构建脚本中的`find`命令参数。另外,可能需要检查OpenWrt的Makefile,看看是否有地方错误地设置了PATH,或者在调用`find`时没有正确限定路径。 另外,用户可能需要更新OpenWrt版本,因为这类问题可能在后续版本中被修复。或者,手动修改引起错误的脚本,将`-execdir`替换为`-exec`,但需要注意安全性影响。还可以尝试在构建时清除之前的构建文件,确保没有残留文件导致问题。 需要确认这些方法是否适用,并给出具体步骤,比如如何临时修改PATH,或者如何找到并修改相关的Makefile或脚本文件。同时,提醒用户备份和谨慎操作,避免引入其他问题。</think>在OpenWrt构建过程中遇到`find: The current path is included in the PATH variable... execdir insecure`错误,通常由以下原因和解决方案构成: ### 错误分析 1. **环境变量污染**:构建脚本的PATH变量包含当前目录`.`,触发`find -execdir`的安全限制[^3] 2. **脚本兼容性问题**:部分旧版本Makefile使用非标准路径调用find命令 ### 解决方案 #### 方法1:临时清除PATH ```bash export PATH=$(echo $PATH | sed 's/:.:/:/g; s/^://; s/:$//') make clean && make ``` #### 方法2:修改构建配置 在`include/prereq-build.mk`中增加路径过滤: ```makefile export PATH := $(filter-out .:,$(PATH)) ``` #### 方法3:升级基础组件 ```bash # 更新findutils包 sudo apt install findutils --upgrade ``` #### 方法4:修改find参数 定位触发错误的Makefile,将: ```bash find ... -execdir ``` 改为: ```bash find ... -exec ``` ### 预防措施 1. 定期执行`make clean`清除旧构建文件[^3] 2. 使用官方推荐环境: ```bash sudo apt remove --purge findutils sudo apt install build-essential libncurses-dev git ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值