Compare commits
12 Commits
618b26c8c4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a31d1e133 | |||
| 9b65834b12 | |||
| b2473d60d5 | |||
| ebd1227d82 | |||
| 9f441d3fb6 | |||
| b0fff11f1f | |||
| 7f159889c1 | |||
| 5351983812 | |||
| c4510ef554 | |||
| dbdc68d7ab | |||
| ff8c43208e | |||
| 3241f7e9a7 |
@ -7,6 +7,10 @@ root = true
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
|
||||
11
.gitignore
vendored
11
.gitignore
vendored
@ -11,7 +11,16 @@
|
||||
.modules.order.cmd
|
||||
.Module.symvers.cmd
|
||||
|
||||
*.dmp
|
||||
|
||||
.config
|
||||
.config.old
|
||||
|
||||
Module.symvers
|
||||
modules.order
|
||||
compile_commands.json
|
||||
|
||||
output/
|
||||
/.cache/
|
||||
|
||||
/include/
|
||||
/output/
|
||||
|
||||
97
03-Bus/01-Platform/01-osdev/Makefile
Normal file
97
03-Bus/01-Platform/01-osdev/Makefile
Normal file
@ -0,0 +1,97 @@
|
||||
#*******************************************************************************
|
||||
# HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 2020.10.21
|
||||
# Description :
|
||||
# Note : yegaoyang@hikvision.com.cn Modified 2020.10.21
|
||||
#*******************************************************************************
|
||||
|
||||
#*******************************************************************************
|
||||
# Path information
|
||||
#*******************************************************************************
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
DRIVER_DIR := $(realpath $(LOCAL_DIR)/../../..)
|
||||
KERNEL_DIR ?= /home/gaoyang3513/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd
|
||||
#KERNEL_DIR ?= $(HOME)/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd/
|
||||
|
||||
# ParDirectory
|
||||
LIBS_DIR :=
|
||||
INCLUDE_DIR :=
|
||||
|
||||
# Subdirectory
|
||||
|
||||
# Output
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
|
||||
#*******************************************************************************
|
||||
# Variables
|
||||
#*******************************************************************************
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
MOD_NAME := osal
|
||||
|
||||
#*******************************************************************************
|
||||
# Compile configure
|
||||
#*******************************************************************************
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= ${HOME}/Source/06-SG20x/02-Projects/SDK_SG200x_V2/host-tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
OBJDUMP := $(CROSS_COMPILE)objdump
|
||||
|
||||
export ARCH CROSS_COMPILE
|
||||
|
||||
#*******************************************************************************
|
||||
# Targets
|
||||
#*******************************************************************************
|
||||
# Read auto.conf if it exists, otherwise ignore
|
||||
-include $(DRIVER_DIR)/include/config/auto.conf
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
ifeq ($(CONFIG_DRIVER_BUS_PLATFORM_OSDEV),)
|
||||
all:
|
||||
$(Q)echo -n ""
|
||||
install:
|
||||
$(Q)echo "[SKIP] OSAL_osdev"
|
||||
else ifeq ($(KERNELRELEASE),)
|
||||
all: init
|
||||
@$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES)
|
||||
# @$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private
|
||||
@$(OBJDUMP) -hdS $(MOD_NAME).o > $(MOD_NAME).dmp
|
||||
|
||||
clean:
|
||||
# File
|
||||
@for n in *.o *.ko *.mod.c *.mod *.cmd *.symvers *.order; do \
|
||||
find $(LOCAL_DIR) -type f -name $$n -exec rm {} \;;\
|
||||
done
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
@if [ -d $(LOCAL_DIR)/.tmp_versions ]; then rm -rf $(LOCAL_DIR)/.tmp_versions; fi;
|
||||
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)/lib/modules/private
|
||||
@install -m 644 -D $(MOD_NAME).ko $(INSTALL_DIR)/lib/modules/private;
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR)
|
||||
|
||||
else
|
||||
obj-m := $(MOD_NAME).o
|
||||
|
||||
$(MOD_NAME)-objs := OSAL_osdev.o
|
||||
|
||||
INC_DIRS :=
|
||||
|
||||
ccflags-y +=
|
||||
|
||||
EXTRA_CFLAGS += -Wno-error=date-time # Fix compile error on gcc 4.9 and later
|
||||
EXTRA_CFLAGS += -Wno-date-time -g
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
186
03-Bus/01-Platform/01-osdev/OSAL_osdev.c
Normal file
186
03-Bus/01-Platform/01-osdev/OSAL_osdev.c
Normal file
@ -0,0 +1,186 @@
|
||||
/*******************************************************************************
|
||||
* HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
* Author :
|
||||
* Version : V1.0.0 2024.11.15
|
||||
* Description :
|
||||
* Note : anonymity@hikvision.com.cn Modified 2024.11.15
|
||||
******************************************************************************/
|
||||
#include <stdarg.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kdev_t.h> // MKDEV
|
||||
|
||||
#include "OSAL_osdev.h"
|
||||
|
||||
struct device osal_bus = {
|
||||
.init_name = "osal",
|
||||
};
|
||||
|
||||
struct bus_type osal_bus_type = {
|
||||
.name = "osal",
|
||||
};
|
||||
|
||||
struct osdev_device { // Object
|
||||
struct osdev osdev; // Proxy
|
||||
struct device dev;
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct osdev_driver {
|
||||
struct device_driver drv;
|
||||
};
|
||||
|
||||
static void osadev_device_release(struct device *dev)
|
||||
{
|
||||
struct osdev_device *osdev_obj = container_of(dev, struct osdev_device, dev);
|
||||
|
||||
kfree(osdev_obj);
|
||||
}
|
||||
|
||||
OSAL_osdev *OSAL_osdevAlloc(const char *name, int id)
|
||||
{
|
||||
struct device *dev = NULL;
|
||||
struct osdev *osdev = NULL;
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
osdev_obj = kzalloc(sizeof(struct osdev_device) + strlen(name) + 1, GFP_KERNEL);
|
||||
if (!osdev_obj) {
|
||||
pr_err("ErrNo(%ld), alloc memory for OSAL_sysDevice failed.", PTR_ERR(dev));
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
osdev = &(osdev_obj->osdev);
|
||||
dev = &(osdev_obj->dev);
|
||||
|
||||
strcpy(osdev_obj->name, name);
|
||||
osdev->name = osdev_obj->name;
|
||||
osdev->id = id;
|
||||
device_initialize(dev);
|
||||
dev->release = osadev_device_release;
|
||||
|
||||
osdev->obj = osdev;
|
||||
|
||||
return (OSAL_osdev *)osdev;
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevAlloc);
|
||||
|
||||
int OSAL_osdevRegister(OSAL_osdev *osdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *dev = NULL;
|
||||
struct osdev *osdev_tmp = NULL;
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
struct osdev_device *osdev_parent = NULL;
|
||||
|
||||
if (osdev == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!osdev->obj) {
|
||||
osdev_tmp = OSAL_osdevAlloc(osdev->name, osdev->id);
|
||||
osdev->obj = osdev_tmp;
|
||||
}
|
||||
else {
|
||||
osdev_tmp = osdev->obj;
|
||||
osdev_parent = container_of(osdev_tmp, struct osdev_device, osdev);
|
||||
}
|
||||
osdev_obj = container_of(osdev_tmp->obj, struct osdev_device, osdev);
|
||||
dev = &(osdev_obj->dev);
|
||||
|
||||
dev_set_name(dev, "%s.%d", osdev->name, osdev->id);
|
||||
dev_set_drvdata(dev, osdev_obj);
|
||||
dev->bus = &osal_bus_type;
|
||||
dev->devt = MKDEV(0, 0);
|
||||
dev->parent = osdev_parent ? &osdev_parent->dev : &osal_bus;
|
||||
|
||||
ret = device_add(dev);
|
||||
if (ret) {
|
||||
pr_err("ErrNo(%d), add device failed.", ret);
|
||||
put_device(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevRegister);
|
||||
|
||||
void OSAL_osdevUnregister(OSAL_osdev *osdev)
|
||||
{
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
if (osdev == NULL || osdev->obj == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return;
|
||||
}
|
||||
|
||||
osdev_obj = container_of(osdev->obj, struct osdev_device, osdev);
|
||||
|
||||
device_del(&osdev_obj->dev);
|
||||
put_device(&osdev_obj->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevUnregister);
|
||||
|
||||
inline void *OSAL_osdevGetDrvdata(const OSAL_osdev *osdev)
|
||||
{
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
if (osdev == NULL || osdev->obj == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
osdev_obj = container_of(osdev->obj, struct osdev_device, osdev);
|
||||
|
||||
return dev_get_drvdata(&osdev_obj->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevGetDrvdata);
|
||||
|
||||
inline void OSAL_osdevSetDrvdata(OSAL_osdev *osdev, void *data)
|
||||
{
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
if (osdev == NULL || osdev->obj == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return;
|
||||
}
|
||||
|
||||
osdev_obj = container_of(osdev->obj, struct osdev_device, osdev);
|
||||
|
||||
dev_set_drvdata(&osdev_obj->dev, data);
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevSetDrvdata);
|
||||
|
||||
int __init OSAL_osdevInit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = device_register(&osal_bus);
|
||||
if (ret) {
|
||||
pr_err("ErrNo(%d), register bus Device[osal] failed.", ret);
|
||||
put_device(&osal_bus);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = bus_register(&osal_bus_type);
|
||||
if (ret) {
|
||||
pr_err("ErrNo(%d), register bus Type[osal] failed.", ret);
|
||||
goto out_unregister_bus;
|
||||
}
|
||||
|
||||
pr_info("OSAL_osdev initialize completed.");
|
||||
|
||||
return ret;
|
||||
|
||||
out_unregister_bus:
|
||||
device_unregister(&osal_bus);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit OSAL_osdevExit(void)
|
||||
{
|
||||
bus_unregister(&osal_bus_type);
|
||||
device_unregister(&osal_bus);
|
||||
}
|
||||
185
03-Bus/01-Platform/01-osdev/OSAL_osdev.c.bak
Normal file
185
03-Bus/01-Platform/01-osdev/OSAL_osdev.c.bak
Normal file
@ -0,0 +1,185 @@
|
||||
/*******************************************************************************
|
||||
* HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
* Author :
|
||||
* Version : V1.0.0 2024.11.15
|
||||
* Description :
|
||||
* Note : anonymity@hikvision.com.cn Modified 2024.11.15
|
||||
******************************************************************************/
|
||||
#include <stdarg.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kdev_t.h> // MKDEV
|
||||
|
||||
#include "OSAL_osdev.h"
|
||||
|
||||
struct device osal_bus = {
|
||||
.init_name = "osal",
|
||||
};
|
||||
|
||||
struct bus_type osal_bus_type = {
|
||||
.name = "osal",
|
||||
};
|
||||
|
||||
struct osdev_device { // Object
|
||||
struct device dev;
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct osdev_driver {
|
||||
struct device_driver drv;
|
||||
};
|
||||
|
||||
static void osadev_device_release(struct device *dev)
|
||||
{
|
||||
struct osdev_device *osdev_obj = container_of(dev, struct osdev_device, dev);
|
||||
|
||||
kfree(osdev_obj);
|
||||
}
|
||||
|
||||
OSAL_osdev *OSAL_osdevAlloc(const char *name, int id)
|
||||
{
|
||||
struct device *dev = NULL;
|
||||
struct osdev *osdev = NULL;
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
osdev_obj = kzalloc(sizeof(struct osdev_device) + strlen(name) + 1, GFP_KERNEL);
|
||||
if (!osdev_obj) {
|
||||
pr_err("ErrNo(%ld), alloc memory for OSAL_sysDevice failed.", PTR_ERR(dev));
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
osdev = &(osdev_obj->osdev);
|
||||
dev = &(osdev_obj->dev);
|
||||
|
||||
strcpy(osdev_obj->name, name);
|
||||
osdev->name = osdev_obj->name;
|
||||
osdev->id = id;
|
||||
device_initialize(dev);
|
||||
dev->release = osadev_device_release;
|
||||
|
||||
osdev->obj = osdev;
|
||||
|
||||
return (OSAL_osdev *)osdev;
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevAlloc);
|
||||
|
||||
int OSAL_osdevRegister(OSAL_osdev *osdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *dev = NULL;
|
||||
struct osdev *osdev_tmp = NULL;
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
struct osdev_device *osdev_parent = NULL;
|
||||
|
||||
if (osdev == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!osdev->obj) {
|
||||
osdev_tmp = OSAL_osdevAlloc(osdev->name, osdev->id);
|
||||
osdev->obj = osdev_tmp;
|
||||
}
|
||||
else {
|
||||
osdev_tmp = osdev->obj;
|
||||
osdev_parent = container_of(osdev_tmp, struct osdev_device, osdev);
|
||||
}
|
||||
osdev_obj = container_of(osdev_tmp->obj, struct osdev_device, osdev);
|
||||
dev = &(osdev_obj->dev);
|
||||
|
||||
dev_set_name(dev, "%s.%d", osdev->name, osdev->id);
|
||||
dev_set_drvdata(dev, osdev_obj);
|
||||
dev->bus = &osal_bus_type;
|
||||
dev->devt = MKDEV(0, 0);
|
||||
dev->parent = osdev_parent ? &osdev_parent->dev : &osal_bus;
|
||||
|
||||
ret = device_add(dev);
|
||||
if (ret) {
|
||||
pr_err("ErrNo(%d), add device failed.", ret);
|
||||
put_device(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevRegister);
|
||||
|
||||
void OSAL_osdevUnregister(OSAL_osdev *osdev)
|
||||
{
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
if (osdev == NULL || osdev->obj == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return;
|
||||
}
|
||||
|
||||
osdev_obj = container_of(osdev->obj, struct osdev_device, osdev);
|
||||
|
||||
device_del(&osdev_obj->dev);
|
||||
put_device(&osdev_obj->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevUnregister);
|
||||
|
||||
inline void *OSAL_osdevGetDrvdata(const OSAL_osdev *osdev)
|
||||
{
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
if (osdev == NULL || osdev->obj == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
osdev_obj = container_of(osdev->obj, struct osdev_device, osdev);
|
||||
|
||||
return dev_get_drvdata(&osdev_obj->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevGetDrvdata);
|
||||
|
||||
inline void OSAL_osdevSetDrvdata(OSAL_osdev *osdev, void *data)
|
||||
{
|
||||
struct osdev_device *osdev_obj = NULL;
|
||||
|
||||
if (osdev == NULL || osdev->obj == NULL) {
|
||||
pr_err("Error, null pointer exception.");
|
||||
return;
|
||||
}
|
||||
|
||||
osdev_obj = container_of(osdev->obj, struct osdev_device, osdev);
|
||||
|
||||
dev_set_drvdata(&osdev_obj->dev, data);
|
||||
}
|
||||
EXPORT_SYMBOL(OSAL_osdevSetDrvdata);
|
||||
|
||||
int __init OSAL_osdevInit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = device_register(&osal_bus);
|
||||
if (ret) {
|
||||
pr_err("ErrNo(%d), register bus Device[osal] failed.", ret);
|
||||
put_device(&osal_bus);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = bus_register(&osal_bus_type);
|
||||
if (ret) {
|
||||
pr_err("ErrNo(%d), register bus Type[osal] failed.", ret);
|
||||
goto out_unregister_bus;
|
||||
}
|
||||
|
||||
pr_info("OSAL_osdev initialize completed.");
|
||||
|
||||
return ret;
|
||||
|
||||
out_unregister_bus:
|
||||
device_unregister(&osal_bus);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit OSAL_osdevExit(void)
|
||||
{
|
||||
bus_unregister(&osal_bus_type);
|
||||
device_unregister(&osal_bus);
|
||||
}
|
||||
29
03-Bus/01-Platform/01-osdev/OSAL_osdev.h
Normal file
29
03-Bus/01-Platform/01-osdev/OSAL_osdev.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*******************************************************************************
|
||||
* HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
* Author :
|
||||
* Version : V1.0.0 2024.11.15
|
||||
* Description :
|
||||
* Note : anonymity@hikvision.com.cn Modified 2024.11.15
|
||||
******************************************************************************/
|
||||
#ifndef INCLUDE_WIDGET_OSAL_OSDEV_H_
|
||||
#define INCLUDE_WIDGET_OSAL_OSDEV_H_
|
||||
|
||||
typedef struct osdev {
|
||||
int id;
|
||||
const char *name;
|
||||
void *obj;
|
||||
} OSAL_osdev;
|
||||
|
||||
typedef struct osdrv {
|
||||
int (*probe)(struct osdev *);
|
||||
int (*remove)(struct osdev *);
|
||||
void *obj;
|
||||
} OSAL_osdrv;
|
||||
|
||||
OSAL_osdev *OSAL_osdevAlloc(const char *name, int id);
|
||||
int OSAL_osdevRegister(OSAL_osdev *osdev);
|
||||
void OSAL_osdevUnregister(OSAL_osdev *osdev);
|
||||
void *OSAL_osdevGetDrvdata(const OSAL_osdev *osdev);
|
||||
void OSAL_osdevSetDrvdata(OSAL_osdev *osdev, void *data);
|
||||
|
||||
#endif /* INCLUDE_WIDGET_OSAL_OSDEV_H_ */
|
||||
28
03-Bus/01-Platform/01-osdev/OSAL_osdev.h.bak
Normal file
28
03-Bus/01-Platform/01-osdev/OSAL_osdev.h.bak
Normal file
@ -0,0 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
* Author :
|
||||
* Version : V1.0.0 2024.11.15
|
||||
* Description :
|
||||
* Note : anonymity@hikvision.com.cn Modified 2024.11.15
|
||||
******************************************************************************/
|
||||
#ifndef INCLUDE_WIDGET_OSAL_OSDEV_H_
|
||||
#define INCLUDE_WIDGET_OSAL_OSDEV_H_
|
||||
|
||||
typedef struct osdev {
|
||||
int id;
|
||||
const char *name;
|
||||
void *obj;
|
||||
} OSAL_osdev;
|
||||
|
||||
typedef struct osdrv {
|
||||
int (*probe)(struct osdev *);
|
||||
int (*remove)(struct osdev *);
|
||||
void *obj;
|
||||
} OSAL_osdrv;
|
||||
|
||||
int OSAL_osdevRegister(OSAL_osdev *osdev);
|
||||
void OSAL_osdevUnregister(OSAL_osdev *osdev);
|
||||
void *OSAL_osdevGetDrvdata(const OSAL_osdev *osdev);
|
||||
void OSAL_osdevSetDrvdata(OSAL_osdev *osdev, void *data);
|
||||
|
||||
#endif /* INCLUDE_WIDGET_OSAL_OSDEV_H_ */
|
||||
3
03-Bus/01-Platform/Kconfig
Normal file
3
03-Bus/01-Platform/Kconfig
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
config DRIVER_BUS_PLATFORM_OSDEV
|
||||
bool "OSAL osdev driver"
|
||||
70
03-Bus/03-SPI/01-NFC_PN5180/Makefile
Normal file
70
03-Bus/03-SPI/01-NFC_PN5180/Makefile
Normal file
@ -0,0 +1,70 @@
|
||||
#------------------------------------------------------------------------------#
|
||||
# All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Description :
|
||||
# Note : gaoyang3513@163.com Modified 202x.01.01
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Path information
|
||||
#------------------------------------------------------------------------------#
|
||||
# Top directories
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
KERNEL_DIR ?= $(realpath $(LOCAL_DIR)/../../../../../linux_5.10/build/kernel_output)
|
||||
|
||||
# Subdirectories
|
||||
|
||||
# Output directories
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Variables
|
||||
#------------------------------------------------------------------------------#
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Compile configure
|
||||
#------------------------------------------------------------------------------#
|
||||
export ARCH ?= riscv
|
||||
export CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Targets
|
||||
#------------------------------------------------------------------------------#
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-m += pn5180.o
|
||||
|
||||
else
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
|
||||
all: init
|
||||
@$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES)
|
||||
# @$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private
|
||||
|
||||
clean:
|
||||
# File
|
||||
@for n in *.o *.ko *.mod.c *.mod *.cmd *.symvers *.order; do \
|
||||
find $(LOCAL_DIR) -type f -name $$n -exec rm {} \;;\
|
||||
done
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
@if [ -d $(LOCAL_DIR)/.tmp_versions ]; then rm -rf $(LOCAL_DIR)/.tmp_versions; fi;
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
70
03-Bus/03-SPI/02-Sub1G_CMT2301/Makefile
Normal file
70
03-Bus/03-SPI/02-Sub1G_CMT2301/Makefile
Normal file
@ -0,0 +1,70 @@
|
||||
#------------------------------------------------------------------------------#
|
||||
# All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Description :
|
||||
# Note : gaoyang3513@163.com Modified 202x.01.01
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Path information
|
||||
#------------------------------------------------------------------------------#
|
||||
# Top directories
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
KERNEL_DIR ?= $(realpath $(LOCAL_DIR)/../../../../../linux_5.10/build/kernel_output)
|
||||
|
||||
# Subdirectories
|
||||
|
||||
# Output directories
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Variables
|
||||
#------------------------------------------------------------------------------#
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Compile configure
|
||||
#------------------------------------------------------------------------------#
|
||||
export ARCH ?= riscv
|
||||
export CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Targets
|
||||
#------------------------------------------------------------------------------#
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-m += cmt2301.o
|
||||
|
||||
else
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
|
||||
all: init
|
||||
@$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES)
|
||||
# @$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private
|
||||
|
||||
clean:
|
||||
# File
|
||||
@for n in *.o *.ko *.mod.c *.mod *.cmd *.symvers *.order; do \
|
||||
find $(LOCAL_DIR) -type f -name $$n -exec rm {} \;;\
|
||||
done
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
@if [ -d $(LOCAL_DIR)/.tmp_versions ]; then rm -rf $(LOCAL_DIR)/.tmp_versions; fi;
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
75
03-Bus/03-SPI/02-Sub1G_CMT2301/cmt2301.c
Normal file
75
03-Bus/03-SPI/02-Sub1G_CMT2301/cmt2301.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define IS_USE_STATIC_PLATFORM_DATA 0
|
||||
|
||||
struct CHIP {
|
||||
struct spi_device *spi;
|
||||
};
|
||||
|
||||
#if IS_USE_STATIC_PLATFORM_DATA
|
||||
struct CHIP_platform_data {
|
||||
int spi_ch;
|
||||
};
|
||||
#endif // IS_USE_STATIC_PLATFORM_DATA
|
||||
|
||||
static int CHIP_probe(struct spi_device *spi)
|
||||
{
|
||||
struct CHIP *chip;
|
||||
#if IS_USE_STATIC_PLATFORM_DATA
|
||||
struct CHIP_platform_data *pdata;
|
||||
|
||||
/* assuming the driver requires board-specific data: */
|
||||
pdata = (struct CHIP_platform_data *)&spi->dev.platform_data;
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
#endif // IS_USE_STATIC_PLATFORM_DATA
|
||||
|
||||
/* get memory for driver's per-chip state */
|
||||
chip = kzalloc(sizeof *chip, GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CHIP_remove(struct spi_device *spi)
|
||||
{
|
||||
struct CHIP *chip = NULL;
|
||||
|
||||
chip = (struct CHIP *)spi_get_drvdata(spi);
|
||||
|
||||
kfree(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id CHIP_of_match[] = {
|
||||
{ .compatible = "nxp,pn5180", },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, CHIP_of_match); // Used by file2alias, which indicated what devices are support with this drive.
|
||||
#endif // CONFIG_OF
|
||||
|
||||
static struct spi_driver CHIP_driver = {
|
||||
.driver = {
|
||||
.name = "CHIP",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_OF
|
||||
.of_match_table = CHIP_of_match,
|
||||
#endif // CONFIG_OF
|
||||
},
|
||||
.probe = CHIP_probe,
|
||||
.remove = CHIP_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(CHIP_driver);
|
||||
|
||||
MODULE_AUTHOR("Gao yang <gaoyang3513@163.com>");
|
||||
MODULE_DESCRIPTION("NXP PN5180 NFC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
76
03-Bus/03-SPI/Makefile
Normal file
76
03-Bus/03-SPI/Makefile
Normal file
@ -0,0 +1,76 @@
|
||||
#------------------------------------------------------------------------------#
|
||||
# All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Description :
|
||||
# Note : gaoyang3513@163.com Modified 202x.01.01
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Path information
|
||||
#------------------------------------------------------------------------------#
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
# Subdirectory
|
||||
PN5180_DIR := $(LOCAL_DIR)/01-NFC_PN5180
|
||||
CMT2301_DIR := $(LOCAL_DIR)/02-Sub1G_CMT2301
|
||||
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Variables
|
||||
#------------------------------------------------------------------------------#
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
SUB_DIRS := $(CMT2301_DIR) $(PN5180_DIR)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Compile configure
|
||||
#------------------------------------------------------------------------------#
|
||||
ARCH ?= riscv
|
||||
CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
export ARCH CROSS_COMPILE
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Targets
|
||||
#------------------------------------------------------------------------------#
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-y += $(SUB_DIRS)
|
||||
|
||||
#INC_DIRS := $(INCLUDE_DIR)/generated
|
||||
#subdir-ccflags-y += $(addprefix -I, $(INC_DIRS))
|
||||
|
||||
else # !KERNELRELEASE
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
|
||||
all: init
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) -C $$sub; \
|
||||
$(MAKE) install INSTALL_DIR=$(OUTPUT_DIR) -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
|
||||
clean:
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) clean -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
endif # !KERNELRELEASE
|
||||
13
03-Bus/Kconfig
Normal file
13
03-Bus/Kconfig
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
config DRIVER_BUS_PLATFORM
|
||||
bool "Platform device driver"
|
||||
|
||||
if DRIVER_BUS_PLATFORM
|
||||
source "03-Bus/01-Platform/Kconfig"
|
||||
endif # DRIVER_BUS_PLATFORM
|
||||
|
||||
config DRIVER_BUS_I2C
|
||||
bool "I2C device driver"
|
||||
|
||||
config DRIVER_BUS_SPI
|
||||
bool "SPI device driver"
|
||||
87
04-Debug/01-Panic/Makefile
Normal file
87
04-Debug/01-Panic/Makefile
Normal file
@ -0,0 +1,87 @@
|
||||
#*******************************************************************************
|
||||
# HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 2020.10.21
|
||||
# Description :
|
||||
# Note : yegaoyang@hikvision.com.cn Modified 2020.10.21
|
||||
#*******************************************************************************
|
||||
|
||||
#*******************************************************************************
|
||||
# Path information
|
||||
#*******************************************************************************
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
KERNEL_DIR ?= /home/gaoyang3513/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd
|
||||
#KERNEL_DIR ?= $(HOME)/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd/
|
||||
|
||||
# ParDirectory
|
||||
LIBS_DIR :=
|
||||
INCLUDE_DIR :=
|
||||
|
||||
# Subdirectory
|
||||
|
||||
# Output
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
|
||||
#*******************************************************************************
|
||||
# Variables
|
||||
#*******************************************************************************
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
MOD_NAME := test_panic
|
||||
|
||||
#*******************************************************************************
|
||||
# Compile configure
|
||||
#*******************************************************************************
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= ${HOME}/Source/06-SG20x/02-Projects/SDK_SG200x_V2/host-tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
OBJDUMP := $(CROSS_COMPILE)objdump
|
||||
|
||||
export ARCH CROSS_COMPILE
|
||||
|
||||
#*******************************************************************************
|
||||
# Targets
|
||||
#*******************************************************************************
|
||||
.PHONY: all install clean
|
||||
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
all: init
|
||||
@$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES)
|
||||
# @$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private
|
||||
@$(OBJDUMP) -hdS test_ps.o > test_ps.dmp
|
||||
|
||||
clean:
|
||||
# File
|
||||
@for n in *.o *.ko *.mod.c *.mod *.cmd *.symvers *.order; do \
|
||||
find $(LOCAL_DIR) -type f -name $$n -exec rm {} \;;\
|
||||
done
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
@if [ -d $(LOCAL_DIR)/.tmp_versions ]; then rm -rf $(LOCAL_DIR)/.tmp_versions; fi;
|
||||
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)/lib/modules/private
|
||||
@install -m 644 -D $(MOD_NAME).ko $(INSTALL_DIR)/lib/modules/private;
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR)
|
||||
|
||||
else
|
||||
obj-m := $(MOD_NAME).o
|
||||
|
||||
$(MOD_NAME)-objs := test_ps.o
|
||||
|
||||
INC_DIRS :=
|
||||
|
||||
ccflags-y +=
|
||||
|
||||
EXTRA_CFLAGS += -Wno-error=date-time # Fix compile error on gcc 4.9 and later
|
||||
EXTRA_CFLAGS += -Wno-date-time -g
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
167
04-Debug/01-Panic/test_ps.c
Normal file
167
04-Debug/01-Panic/test_ps.c
Normal file
@ -0,0 +1,167 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
static unsigned int test_type;
|
||||
module_param(test_type, uint, 0400);
|
||||
MODULE_PARM_DESC(test_type, "set to 1 to try to OOM (default 0)");
|
||||
|
||||
static int trigger_oops(void)
|
||||
{
|
||||
int *ptr = (int *)0; // 强制类型转换0地址为指针并尝试读取
|
||||
|
||||
printk(KERN_ALERT "Dereferenced NULL pointer value: %d\n", *ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_oob(void) {
|
||||
char *buffer;
|
||||
int *out_of_bounds;
|
||||
|
||||
printk(KERN_INFO "Out-of-bounds memory access test module loaded\n");
|
||||
|
||||
// Allocate a small buffer
|
||||
// buffer = kmalloc(256, GFP_KERNEL);
|
||||
buffer = vmalloc(PAGE_SIZE * 2);
|
||||
if (!buffer) {
|
||||
printk(KERN_ERR "Failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// Attempt to access memory out of bounds
|
||||
out_of_bounds = (int *)(buffer + PAGE_SIZE * 3); // Move pointer to the end of the buffer
|
||||
*out_of_bounds = 0; // This should cause an out-of-bounds write
|
||||
|
||||
printk(KERN_INFO "Out-of-bounds Ofst[%lu] memory access performed\n", 256 + PAGE_SIZE);
|
||||
|
||||
kfree(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_oom(void)
|
||||
{
|
||||
void *memory = NULL;
|
||||
size_t memory_size = 0;
|
||||
|
||||
printk(KERN_INFO "oom_trigger: Initializing the oom_trigger LKM\n");
|
||||
|
||||
memory_size = 100*1024*1024;
|
||||
while (1) { // 尝试分配大块内存
|
||||
memory = vmalloc(memory_size);
|
||||
if (!memory) {
|
||||
printk(KERN_ALERT "oom_trigger: Memory allocation failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// 仅为防止编译器优化,实际不访问分配的内存
|
||||
memset(memory, 0, memory_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_data = 0;
|
||||
static struct rcu_head test_rcu_head;
|
||||
|
||||
static void bad_rcu_callback(struct rcu_head *head)
|
||||
{
|
||||
// 违规操作:在RCU回调函数中睡眠,这可能导致RCU grace period过长
|
||||
msleep(1000);
|
||||
|
||||
// 违规操作:修改被RCU保护的数据结构
|
||||
test_data++; // 不应在RCU回调中修改全局变量
|
||||
|
||||
pr_info("Bad RCU callback executed\n");
|
||||
}
|
||||
|
||||
static void trigger_rcu(void)
|
||||
{
|
||||
pr_info("RCU error module loaded\n");
|
||||
|
||||
call_rcu(&test_rcu_head, bad_rcu_callback);
|
||||
}
|
||||
|
||||
static int is_ready_thread1, is_ready_thread2;
|
||||
static struct task_struct *thread1;
|
||||
static struct task_struct *thread2;
|
||||
|
||||
static DEFINE_MUTEX(mutex_a);
|
||||
static DEFINE_MUTEX(mutex_b);
|
||||
|
||||
static int thread_func(void *data)
|
||||
{
|
||||
char *name = (char *) data;
|
||||
|
||||
if (!strcmp(name, "Thread1")) {
|
||||
printk(KERN_INFO "%s: Acquiring mutex A...\n", name);
|
||||
mutex_lock(&mutex_a);
|
||||
is_ready_thread1 = 1;
|
||||
while (!is_ready_thread2);
|
||||
printk(KERN_INFO "%s: Got mutex A. Now trying to acquire mutex B...\n", name);
|
||||
mutex_lock(&mutex_b); // This will block, causing deadlock
|
||||
printk(KERN_INFO "%s: Got mutex B.\n", name);
|
||||
} else {
|
||||
printk(KERN_INFO "%s: Acquiring mutex B...\n", name);
|
||||
mutex_lock(&mutex_b);
|
||||
is_ready_thread2 = 1;
|
||||
while (!is_ready_thread1);
|
||||
printk(KERN_INFO "%s: Got mutex B. Now trying to acquire mutex A...\n", name);
|
||||
mutex_lock(&mutex_a); // This will block, causing deadlock
|
||||
printk(KERN_INFO "%s: Got mutex A.\n", name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_deadlock(void)
|
||||
{
|
||||
thread1 = kthread_run(thread_func, (void *) "Thread1", "thread1");
|
||||
if (IS_ERR(thread1)) {
|
||||
printk(KERN_ERR "Failed to create thread1\n");
|
||||
return PTR_ERR(thread1);
|
||||
}
|
||||
|
||||
thread2 = kthread_run(thread_func, (void *) "Thread2", "thread2");
|
||||
if (IS_ERR(thread2)) {
|
||||
printk(KERN_ERR "Failed to create thread2\n");
|
||||
kthread_stop(thread1);
|
||||
return PTR_ERR(thread2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_init(void) {
|
||||
if (test_type == 0)
|
||||
trigger_oops();
|
||||
else if (test_type == 1)
|
||||
trigger_oom();
|
||||
else if (test_type == 2)
|
||||
trigger_rcu();
|
||||
else if (test_type == 3)
|
||||
trigger_deadlock();
|
||||
else if (test_type == 4)
|
||||
trigger_oob();
|
||||
|
||||
return 0; // 加载模块不应该有返回值,但这里返回0避免编译警告。
|
||||
}
|
||||
|
||||
static void __exit trigger_exit(void) {
|
||||
if (test_type == 3) {
|
||||
kthread_stop(thread1);
|
||||
kthread_stop(thread2);
|
||||
printk(KERN_INFO "Deadlock trigger exit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
module_init(trigger_init);
|
||||
module_exit(trigger_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -1,33 +1,41 @@
|
||||
#*******************************************************************************
|
||||
# HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Version : V1.0.0 2020.10.21
|
||||
# Description :
|
||||
# Note : gaoyang3513@163.com Modified 2020.10.21
|
||||
# Note : yegaoyang@hikvision.com.cn Modified 2020.10.21
|
||||
#*******************************************************************************
|
||||
|
||||
#*******************************************************************************
|
||||
# Path information
|
||||
#*******************************************************************************
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
KERNEL_DIR ?= $(realpath $(LOCAL_DIR)/../../../../linux_5.10)
|
||||
KERNEL_DIR ?= /home/gaoyang3513/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd
|
||||
#KERNEL_DIR ?= $(HOME)/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd/
|
||||
|
||||
# ParDirectory
|
||||
LIBS_DIR :=
|
||||
INCLUDE_DIR :=
|
||||
|
||||
# Subdirectory
|
||||
SUB_DIRS := $(LOCAL_DIR)/01-Panic
|
||||
|
||||
# Output
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
|
||||
#*******************************************************************************
|
||||
# Variables
|
||||
#*******************************************************************************
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
MOD_NAME := test_panic
|
||||
|
||||
#*******************************************************************************
|
||||
# Compile configure
|
||||
#*******************************************************************************
|
||||
ARCH ?= riscv
|
||||
CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= ${HOME}/Source/06-SG20x/02-Projects/SDK_SG200x_V2/host-tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
@ -35,25 +43,26 @@ AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
export ARCH CROSS_COMPILE
|
||||
|
||||
#*******************************************************************************
|
||||
# Targets
|
||||
#*******************************************************************************
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
.PHONY: init all clean install menuconfig
|
||||
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
all: init
|
||||
@$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES)
|
||||
@$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) -C $$sub || exit "$$?"; \
|
||||
$(MAKE) install INSTALL_DIR=$(OUTPUT_DIR) -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
|
||||
clean:
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) clean -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
@if [ -d $(LOCAL_DIR)/.tmp_versions ]; then rm -rf $(LOCAL_DIR)/.tmp_versions; fi;
|
||||
# File
|
||||
@for f in {Module.symvers,modules.order}; do \
|
||||
if [ -e $$f ]; then rm -rf $$f; fi; \
|
||||
done
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@ -61,9 +70,12 @@ install:
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
|
||||
else
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-m += pn5180.o
|
||||
obj-y += $(SUB_DIRS)
|
||||
|
||||
INC_DIRS :=
|
||||
|
||||
subdir-ccflags-y += $(addprefix -I, $(INC_DIRS))
|
||||
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
114
Kconfig
Normal file
114
Kconfig
Normal file
@ -0,0 +1,114 @@
|
||||
mainmenu "Example Kconfig configuration"
|
||||
|
||||
menu "Modules with the type of bus support"
|
||||
|
||||
config MODULE_BUS
|
||||
bool "Bus device driver"
|
||||
default n
|
||||
|
||||
if MODULE_BUS
|
||||
source "03-Bus/Kconfig"
|
||||
endif # Module_BUS
|
||||
|
||||
endmenu
|
||||
|
||||
#config MODULES
|
||||
# bool "Enable loadable module support"
|
||||
# option modules
|
||||
# default n
|
||||
|
||||
menu "Bool and tristate symbols"
|
||||
|
||||
config BOOL
|
||||
bool "Bool symbol"
|
||||
default y
|
||||
|
||||
config BOOL_DEP
|
||||
bool "Dependent bool symbol"
|
||||
depends on BOOL
|
||||
|
||||
# Mix it up a bit with an 'if' instead of a 'depends on'
|
||||
if BOOL
|
||||
|
||||
config TRI_DEP
|
||||
tristate "Dependent tristate symbol"
|
||||
select SELECTED_BY_TRI_DEP
|
||||
imply IMPLIED_BY_TRI_DEP
|
||||
|
||||
endif
|
||||
|
||||
config TWO_MENU_NODES
|
||||
bool "First prompt"
|
||||
depends on BOOL
|
||||
|
||||
config TRI
|
||||
tristate "Tristate symbol"
|
||||
|
||||
config TWO_MENU_NODES
|
||||
bool "Second prompt"
|
||||
|
||||
comment "These are selected by TRI_DEP"
|
||||
|
||||
config SELECTED_BY_TRI_DEP
|
||||
tristate "Tristate selected by TRI_DEP"
|
||||
|
||||
config IMPLIED_BY_TRI_DEP
|
||||
tristate "Tristate implied by TRI_DEP"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
menu "String, int, and hex symbols"
|
||||
|
||||
config STRING
|
||||
string "String symbol"
|
||||
default "foo"
|
||||
|
||||
config INT
|
||||
int "Int symbol"
|
||||
default 747
|
||||
|
||||
config HEX
|
||||
hex "Hex symbol"
|
||||
default 0xABC
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
menu "Various choices"
|
||||
|
||||
choice BOOL_CHOICE
|
||||
bool "Bool choice"
|
||||
|
||||
config BOOL_CHOICE_SYM_1
|
||||
bool "Bool choice sym 1"
|
||||
|
||||
config BOOL_CHOICE_SYM_2
|
||||
bool "Bool choice sym 2"
|
||||
|
||||
endchoice
|
||||
|
||||
choice TRI_CHOICE
|
||||
tristate "Tristate choice"
|
||||
|
||||
config TRI_CHOICE_SYM_1
|
||||
tristate "Tristate choice sym 1"
|
||||
|
||||
config TRI_CHOICE_SYM_2
|
||||
tristate "Tristate choice sym 2"
|
||||
|
||||
endchoice
|
||||
|
||||
choice OPT_BOOL_CHOICE
|
||||
bool "Optional bool choice"
|
||||
optional
|
||||
|
||||
config OPT_BOOL_CHOICE_SYM_1
|
||||
bool "Optional bool choice sym 1"
|
||||
|
||||
config OPT_BOOL_CHOICE_SYM_2
|
||||
bool "Optional bool choice sym 2"
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
140
Makefile
140
Makefile
@ -1,75 +1,135 @@
|
||||
#*******************************************************************************
|
||||
# HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Description :
|
||||
# Note : gaoyang@.com.cn Modified 2020.10.21
|
||||
#*******************************************************************************
|
||||
# Note : gaoyang3513@163.com.cn Modified 202x.01.01
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# That's our default target when none is given on the command line
|
||||
PHONY := all
|
||||
all:
|
||||
|
||||
#*******************************************************************************
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Path information
|
||||
#*******************************************************************************
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
KERNEL_DIR ?= $(realpath $(LOCAL_DIR)/../../../linux_5.10)
|
||||
# ---------------------------------------------------------------------------- #
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
# SDK directories
|
||||
SDK_TOP ?= $(HOME)/Source/15-SG200x/01-MilkDuo/02-Project/SDK_SG200x_V2.0.0
|
||||
KERNEL_DIR ?= $(SDK_TOP)/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd
|
||||
TOOLCHAIN_DIR ?= $(SDK_TOP)/host-tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin
|
||||
|
||||
# Subdirectory
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
export KERNEL_DIR
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Functions
|
||||
# ---------------------------------------------------------------------------- #
|
||||
define filechk_version.h
|
||||
echo \#define LINUX_VERSION_CODE $(shell \
|
||||
expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
|
||||
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'
|
||||
endef
|
||||
|
||||
#*******************************************************************************
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Variables
|
||||
#*******************************************************************************
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
# ---------------------------------------------------------------------------- #
|
||||
VERSION = 1
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
NAME = Kleptomaniac Octopus
|
||||
|
||||
SUB_DIRS := spi/
|
||||
version_h := include/generated/version.h
|
||||
|
||||
#*******************************************************************************
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
ifeq ("$(origin V)", "command line")
|
||||
KBUILD_VERBOSE = $(V)
|
||||
endif
|
||||
ifndef KBUILD_VERBOSE
|
||||
KBUILD_VERBOSE = 0
|
||||
endif
|
||||
|
||||
ifeq ($(KBUILD_VERBOSE),1)
|
||||
quiet =
|
||||
Q =
|
||||
else
|
||||
quiet = quiet_
|
||||
Q = @
|
||||
endif
|
||||
|
||||
export Q quiet
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Compile configure
|
||||
#*******************************************************************************
|
||||
ARCH ?= riscv
|
||||
CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
# ---------------------------------------------------------------------------- #
|
||||
#CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= aarch64-linux-gnu-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
export ARCH CROSS_COMPILE
|
||||
#*******************************************************************************
|
||||
# Targets
|
||||
#*******************************************************************************
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
PATH := $(TOOLCHAIN_DIR):$(PATH)
|
||||
|
||||
export ARCH CROSS_COMPILE PATH
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Objects
|
||||
# ---------------------------------------------------------------------------- #
|
||||
SUB_DIRS := 03-Bus/01-Platform/01-osdev
|
||||
#$(warning "SUB_DIRS: $(SUB_DIRS)")
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Targets
|
||||
# ---------------------------------------------------------------------------- #
|
||||
.PHONY += init all clean distclean install menuconfig oldconfig $(version_h)
|
||||
|
||||
include scripts/Kbuild.include
|
||||
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
all: init
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(Q)for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) -C $$sub; \
|
||||
$(MAKE) install INSTALL_DIR=$(OUTPUT_DIR) -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
|
||||
clean:
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(Q)for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) clean -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
$(Q)if [ -d $(LOCAL_DIR)/include/config ]; then rm -rf $(LOCAL_DIR)/include/config; fi;
|
||||
$(Q)if [ -d $(LOCAL_DIR)/include/generated ]; then rm -rf $(LOCAL_DIR)/include/generated; fi;
|
||||
$(Q)if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
$(Q)if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
$(Q)mkdir -p $(INSTALL_DIR)
|
||||
$(Q)cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
init: $(version_h)
|
||||
$(Q)mkdir -p $(OUTPUT_DIR);
|
||||
$(Q)mkdir -p include/config include/generated
|
||||
$(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/genconfig.py --sync-dep include/config --header-path include/generated/autoconf.h
|
||||
|
||||
else
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-y += $(SUB_DIRS)
|
||||
oldconfig:
|
||||
$(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/oldconfig.py
|
||||
|
||||
#INC_DIRS := $(INCLUDE_DIR)/generated
|
||||
#subdir-ccflags-y += $(addprefix -I, $(INC_DIRS))
|
||||
%_defconfig:
|
||||
$(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/defconfig.py --kconfig Kconfig configs/$@
|
||||
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
menuconfig:
|
||||
$(Q)mkdir -p include/config include/generated
|
||||
$(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/menuconfig.py Kconfig
|
||||
|
||||
savedefconfig:
|
||||
$(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/savedefconfig.py --kconfig Kconfig --out defconfig
|
||||
|
||||
$(version_h):
|
||||
$(Q)$(call filechk,version.h)
|
||||
|
||||
9
config.h
Normal file
9
config.h
Normal file
@ -0,0 +1,9 @@
|
||||
#define CONFIG_MODULE_BUS 1
|
||||
#define CONFIG_DRIVER_BUS_PLATFORM 1
|
||||
#define CONFIG_DRIVER_BUS_PLATFORM_OSDEV 1
|
||||
#define CONFIG_BOOL 1
|
||||
#define CONFIG_STRING "foo"
|
||||
#define CONFIG_INT 747
|
||||
#define CONFIG_HEX 0xABC
|
||||
#define CONFIG_BOOL_CHOICE_SYM_1 1
|
||||
#define CONFIG_TRI_CHOICE_SYM_1 1
|
||||
3
configs/foo_defconfig
Normal file
3
configs/foo_defconfig
Normal file
@ -0,0 +1,3 @@
|
||||
# CONFIG_MODULES is not set
|
||||
# CONFIG_BOOL is not set
|
||||
CONFIG_TRI_CHOICE_SYM_1=y
|
||||
323
scripts/Kbuild.include
Normal file
323
scripts/Kbuild.include
Normal file
@ -0,0 +1,323 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
####
|
||||
# kbuild: Generic definitions
|
||||
|
||||
# Convenient variables
|
||||
comma := ,
|
||||
quote := "
|
||||
squote := '
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
space_escape := _-_SPACE_-_
|
||||
pound := \#
|
||||
|
||||
###
|
||||
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
|
||||
dot-target = $(dir $@).$(notdir $@)
|
||||
|
||||
###
|
||||
# The temporary file to save gcc -MMD generated dependencies must not
|
||||
# contain a comma
|
||||
depfile = $(subst $(comma),_,$(dot-target).d)
|
||||
|
||||
###
|
||||
# filename of target with directory and extension stripped
|
||||
basetarget = $(basename $(notdir $@))
|
||||
|
||||
###
|
||||
# real prerequisites without phony targets
|
||||
real-prereqs = $(filter-out $(PHONY), $^)
|
||||
|
||||
###
|
||||
# Escape single quote for use in echo statements
|
||||
escsq = $(subst $(squote),'\$(squote)',$1)
|
||||
|
||||
###
|
||||
# Quote a string to pass it to C files. foo => '"foo"'
|
||||
stringify = $(squote)$(quote)$1$(quote)$(squote)
|
||||
|
||||
###
|
||||
# Easy method for doing a status message
|
||||
kecho := :
|
||||
quiet_kecho := echo
|
||||
silent_kecho := :
|
||||
kecho := $($(quiet)kecho)
|
||||
|
||||
###
|
||||
# filechk is used to check if the content of a generated file is updated.
|
||||
# Sample usage:
|
||||
#
|
||||
# filechk_sample = echo $(KERNELRELEASE)
|
||||
# version.h: FORCE
|
||||
# $(call filechk,sample)
|
||||
#
|
||||
# The rule defined shall write to stdout the content of the new file.
|
||||
# The existing file will be compared with the new one.
|
||||
# - If no file exist it is created
|
||||
# - If the content differ the new file is used
|
||||
# - If they are equal no change, and no timestamp update
|
||||
define filechk
|
||||
$(Q)set -e; \
|
||||
mkdir -p $(dir $@); \
|
||||
trap "rm -f $(dot-target).tmp" EXIT; \
|
||||
{ $(filechk_$(1)); } > $(dot-target).tmp; \
|
||||
if [ ! -r $@ ] || ! cmp -s $@ $(dot-target).tmp; then \
|
||||
$(kecho) ' UPD $@'; \
|
||||
mv -f $(dot-target).tmp $@; \
|
||||
fi
|
||||
endef
|
||||
|
||||
######
|
||||
# gcc support functions
|
||||
# See documentation in Documentation/kbuild/makefiles.rst
|
||||
|
||||
# cc-cross-prefix
|
||||
# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-)
|
||||
# Return first <prefix> where a <prefix>gcc is found in PATH.
|
||||
# If no gcc found in PATH with listed prefixes return nothing
|
||||
#
|
||||
# Note: '2>/dev/null' is here to force Make to invoke a shell. Otherwise, it
|
||||
# would try to directly execute the shell builtin 'command'. This workaround
|
||||
# should be kept for a long time since this issue was fixed only after the
|
||||
# GNU Make 4.2.1 release.
|
||||
cc-cross-prefix = $(firstword $(foreach c, $(1), \
|
||||
$(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
|
||||
|
||||
# output directory for tests below
|
||||
TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
|
||||
|
||||
# try-run
|
||||
# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
|
||||
# Exit code chooses option. "$$TMP" serves as a temporary file and is
|
||||
# automatically cleaned up.
|
||||
try-run = $(shell set -e; \
|
||||
TMP=$(TMPOUT)/tmp; \
|
||||
TMPO=$(TMPOUT)/tmp.o; \
|
||||
mkdir -p $(TMPOUT); \
|
||||
trap "rm -rf $(TMPOUT)" EXIT; \
|
||||
if ($(1)) >/dev/null 2>&1; \
|
||||
then echo "$(2)"; \
|
||||
else echo "$(3)"; \
|
||||
fi)
|
||||
|
||||
# as-option
|
||||
# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
|
||||
|
||||
as-option = $(call try-run,\
|
||||
$(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
|
||||
|
||||
# as-instr
|
||||
# Usage: cflags-y += $(call as-instr,instr,option1,option2)
|
||||
|
||||
as-instr = $(call try-run,\
|
||||
printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
|
||||
|
||||
# __cc-option
|
||||
# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586)
|
||||
__cc-option = $(call try-run,\
|
||||
$(1) -Werror $(2) $(3) -c -x c /dev/null -o "$$TMP",$(3),$(4))
|
||||
|
||||
# cc-option
|
||||
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
|
||||
|
||||
cc-option = $(call __cc-option, $(CC),\
|
||||
$(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS),$(1),$(2))
|
||||
|
||||
# cc-option-yn
|
||||
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
|
||||
cc-option-yn = $(call try-run,\
|
||||
$(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
|
||||
|
||||
# cc-disable-warning
|
||||
# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
|
||||
cc-disable-warning = $(call try-run,\
|
||||
$(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
|
||||
|
||||
# cc-ifversion
|
||||
# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
|
||||
cc-ifversion = $(shell [ $(CONFIG_GCC_VERSION)0 $(1) $(2)000 ] && echo $(3) || echo $(4))
|
||||
|
||||
# ld-option
|
||||
# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
|
||||
ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3))
|
||||
|
||||
# ld-version
|
||||
# Note this is mainly for HJ Lu's 3 number binutil versions
|
||||
ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
|
||||
|
||||
# ld-ifversion
|
||||
# Usage: $(call ld-ifversion, -ge, 22252, y)
|
||||
ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4))
|
||||
|
||||
######
|
||||
|
||||
###
|
||||
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
|
||||
# Usage:
|
||||
# $(Q)$(MAKE) $(build)=dir
|
||||
build := -f $(srctree)/scripts/Makefile.build obj
|
||||
|
||||
###
|
||||
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
|
||||
# Usage:
|
||||
# $(Q)$(MAKE) $(dtbinst)=dir
|
||||
dtbinst := -f $(srctree)/scripts/Makefile.dtbinst obj
|
||||
|
||||
###
|
||||
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=
|
||||
# Usage:
|
||||
# $(Q)$(MAKE) $(clean)=dir
|
||||
clean := -f $(srctree)/scripts/Makefile.clean obj
|
||||
|
||||
# echo command.
|
||||
# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
|
||||
echo-cmd = $(if $($(quiet)cmd_$(1)),\
|
||||
echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
|
||||
|
||||
# printing commands
|
||||
cmd = @set -e; $(echo-cmd) $(cmd_$(1))
|
||||
|
||||
###
|
||||
# if_changed - execute command if any prerequisite is newer than
|
||||
# target, or command line has changed
|
||||
# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies
|
||||
# including used config symbols
|
||||
# if_changed_rule - as if_changed but execute rule instead
|
||||
# See Documentation/kbuild/makefiles.rst for more info
|
||||
|
||||
ifneq ($(KBUILD_NOCMDDEP),1)
|
||||
# Check if both commands are the same including their order. Result is empty
|
||||
# string if equal. User may override this check using make KBUILD_NOCMDDEP=1
|
||||
cmd-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \
|
||||
$(subst $(space),$(space_escape),$(strip $(cmd_$1))))
|
||||
else
|
||||
cmd-check = $(if $(strip $(cmd_$@)),,1)
|
||||
endif
|
||||
|
||||
# Replace >$< with >$$< to preserve $ when reloading the .cmd file
|
||||
# (needed for make)
|
||||
# Replace >#< with >$(pound)< to avoid starting a comment in the .cmd file
|
||||
# (needed for make)
|
||||
# Replace >'< with >'\''< to be able to enclose the whole string in '...'
|
||||
# (needed for the shell)
|
||||
make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1)))))
|
||||
|
||||
# Find any prerequisites that are newer than target or that do not exist.
|
||||
# (This is not true for now; $? should contain any non-existent prerequisites,
|
||||
# but it does not work as expected when .SECONDARY is present. This seems a bug
|
||||
# of GNU Make.)
|
||||
# PHONY targets skipped in both cases.
|
||||
newer-prereqs = $(filter-out $(PHONY),$?)
|
||||
|
||||
# Execute command if command has changed or prerequisite(s) are updated.
|
||||
if_changed = $(if $(newer-prereqs)$(cmd-check), \
|
||||
$(cmd); \
|
||||
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
|
||||
|
||||
# Execute the command and also postprocess generated .d dependencies file.
|
||||
if_changed_dep = $(if $(newer-prereqs)$(cmd-check),$(cmd_and_fixdep),@:)
|
||||
|
||||
cmd_and_fixdep = \
|
||||
$(cmd); \
|
||||
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd;\
|
||||
rm -f $(depfile)
|
||||
|
||||
# Usage: $(call if_changed_rule,foo)
|
||||
# Will check if $(cmd_foo) or any of the prerequisites changed,
|
||||
# and if so will execute $(rule_foo).
|
||||
if_changed_rule = $(if $(newer-prereqs)$(cmd-check),$(rule_$(1)),@:)
|
||||
|
||||
###
|
||||
# why - tell why a target got built
|
||||
# enabled by make V=2
|
||||
# Output (listed in the order they are checked):
|
||||
# (1) - due to target is PHONY
|
||||
# (2) - due to target missing
|
||||
# (3) - due to: file1.h file2.h
|
||||
# (4) - due to command line change
|
||||
# (5) - due to missing .cmd file
|
||||
# (6) - due to target not in $(targets)
|
||||
# (1) PHONY targets are always build
|
||||
# (2) No target, so we better build it
|
||||
# (3) Prerequisite is newer than target
|
||||
# (4) The command line stored in the file named dir/.target.cmd
|
||||
# differed from actual command line. This happens when compiler
|
||||
# options changes
|
||||
# (5) No dir/.target.cmd file (used to store command line)
|
||||
# (6) No dir/.target.cmd file and target not listed in $(targets)
|
||||
# This is a good hint that there is a bug in the kbuild file
|
||||
ifeq ($(KBUILD_VERBOSE),2)
|
||||
why = \
|
||||
$(if $(filter $@, $(PHONY)),- due to target is PHONY, \
|
||||
$(if $(wildcard $@), \
|
||||
$(if $(newer-prereqs),- due to: $(newer-prereqs), \
|
||||
$(if $(cmd-check), \
|
||||
$(if $(cmd_$@),- due to command line change, \
|
||||
$(if $(filter $@, $(targets)), \
|
||||
- due to missing .cmd file, \
|
||||
- due to $(notdir $@) not in $$(targets) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
), \
|
||||
- due to target missing \
|
||||
) \
|
||||
)
|
||||
|
||||
echo-why = $(call escsq, $(strip $(why)))
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# When a Kconfig string contains a filename, it is suitable for
|
||||
# passing to shell commands. It is surrounded by double-quotes, and
|
||||
# any double-quotes or backslashes within it are escaped by
|
||||
# backslashes.
|
||||
#
|
||||
# This is no use for dependencies or $(wildcard). We need to strip the
|
||||
# surrounding quotes and the escaping from quotes and backslashes, and
|
||||
# we *do* need to escape any spaces in the string. So, for example:
|
||||
#
|
||||
# Usage: $(eval $(call config_filename,FOO))
|
||||
#
|
||||
# Defines FOO_FILENAME based on the contents of the CONFIG_FOO option,
|
||||
# transformed as described above to be suitable for use within the
|
||||
# makefile.
|
||||
#
|
||||
# Also, if the filename is a relative filename and exists in the source
|
||||
# tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to
|
||||
# be prefixed to *both* command invocation and dependencies.
|
||||
#
|
||||
# Note: We also print the filenames in the quiet_cmd_foo text, and
|
||||
# perhaps ought to have a version specially escaped for that purpose.
|
||||
# But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good
|
||||
# enough. It'll strip the quotes in the common case where there's no
|
||||
# space and it's a simple filename, and it'll retain the quotes when
|
||||
# there's a space. There are some esoteric cases in which it'll print
|
||||
# the wrong thing, but we don't really care. The actual dependencies
|
||||
# and commands *do* get it right, with various combinations of single
|
||||
# and double quotes, backslashes and spaces in the filenames.
|
||||
#
|
||||
###############################################################################
|
||||
#
|
||||
define config_filename
|
||||
ifneq ($$(CONFIG_$(1)),"")
|
||||
$(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1)))))))
|
||||
ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME)))
|
||||
else
|
||||
ifeq ($$(wildcard $$($(1)_FILENAME)),)
|
||||
ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),)
|
||||
$(1)_SRCPREFIX := $(srctree)/
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endef
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
# delete partially updated (i.e. corrupted) files on error
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
# do not delete intermediate files automatically
|
||||
.SECONDARY:
|
||||
526
scripts/Makefile.build
Normal file
526
scripts/Makefile.build
Normal file
@ -0,0 +1,526 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# ==========================================================================
|
||||
# Building
|
||||
# ==========================================================================
|
||||
|
||||
src := $(obj)
|
||||
|
||||
PHONY := __build
|
||||
__build:
|
||||
|
||||
# Init all relevant variables used in kbuild files so
|
||||
# 1) they have correct type
|
||||
# 2) they do not inherit any value from the environment
|
||||
obj-y :=
|
||||
obj-m :=
|
||||
lib-y :=
|
||||
lib-m :=
|
||||
always :=
|
||||
always-y :=
|
||||
always-m :=
|
||||
targets :=
|
||||
subdir-y :=
|
||||
subdir-m :=
|
||||
EXTRA_AFLAGS :=
|
||||
EXTRA_CFLAGS :=
|
||||
EXTRA_CPPFLAGS :=
|
||||
EXTRA_LDFLAGS :=
|
||||
asflags-y :=
|
||||
ccflags-y :=
|
||||
cppflags-y :=
|
||||
ldflags-y :=
|
||||
|
||||
subdir-asflags-y :=
|
||||
subdir-ccflags-y :=
|
||||
|
||||
# Read auto.conf if it exists, otherwise ignore
|
||||
-include include/config/auto.conf
|
||||
|
||||
include scripts/Kbuild.include
|
||||
|
||||
# The filename Kbuild has precedence over Makefile
|
||||
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
|
||||
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
|
||||
include $(kbuild-file)
|
||||
|
||||
include scripts/Makefile.lib
|
||||
|
||||
# Do not include hostprogs rules unless needed.
|
||||
# $(sort ...) is used here to remove duplicated words and excessive spaces.
|
||||
hostprogs := $(sort $(hostprogs))
|
||||
ifneq ($(hostprogs),)
|
||||
include scripts/Makefile.host
|
||||
endif
|
||||
|
||||
# Do not include userprogs rules unless needed.
|
||||
# $(sort ...) is used here to remove duplicated words and excessive spaces.
|
||||
userprogs := $(sort $(userprogs))
|
||||
ifneq ($(userprogs),)
|
||||
include scripts/Makefile.userprogs
|
||||
endif
|
||||
|
||||
ifndef obj
|
||||
$(warning kbuild: Makefile.build is included improperly)
|
||||
endif
|
||||
|
||||
ifeq ($(need-modorder),)
|
||||
ifneq ($(obj-m),)
|
||||
$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.)
|
||||
$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
|
||||
endif
|
||||
endif
|
||||
|
||||
# ===========================================================================
|
||||
|
||||
# subdir-builtin and subdir-modorder may contain duplications. Use $(sort ...)
|
||||
subdir-builtin := $(sort $(filter %/built-in.a, $(real-obj-y)))
|
||||
subdir-modorder := $(sort $(filter %/modules.order, $(obj-m)))
|
||||
|
||||
targets-for-builtin := $(extra-y)
|
||||
|
||||
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
|
||||
targets-for-builtin += $(obj)/lib.a
|
||||
endif
|
||||
|
||||
ifdef need-builtin
|
||||
targets-for-builtin += $(obj)/built-in.a
|
||||
endif
|
||||
|
||||
targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m)))
|
||||
|
||||
ifdef need-modorder
|
||||
targets-for-modules += $(obj)/modules.order
|
||||
endif
|
||||
|
||||
targets += $(targets-for-builtin) $(targets-for-modules)
|
||||
|
||||
# Linus' kernel sanity checking tool
|
||||
ifeq ($(KBUILD_CHECKSRC),1)
|
||||
quiet_cmd_checksrc = CHECK $<
|
||||
cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
|
||||
else ifeq ($(KBUILD_CHECKSRC),2)
|
||||
quiet_cmd_force_checksrc = CHECK $<
|
||||
cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
|
||||
endif
|
||||
|
||||
ifneq ($(KBUILD_EXTRA_WARN),)
|
||||
cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $<
|
||||
endif
|
||||
|
||||
# Compile C sources (.c)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
|
||||
cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) -fverbose-asm -S -o $@ $<
|
||||
|
||||
$(obj)/%.s: $(src)/%.c FORCE
|
||||
$(call if_changed_dep,cc_s_c)
|
||||
|
||||
quiet_cmd_cpp_i_c = CPP $(quiet_modtag) $@
|
||||
cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $<
|
||||
|
||||
$(obj)/%.i: $(src)/%.c FORCE
|
||||
$(call if_changed_dep,cpp_i_c)
|
||||
|
||||
# These mirror gensymtypes_S and co below, keep them in synch.
|
||||
cmd_gensymtypes_c = \
|
||||
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
|
||||
scripts/genksyms/genksyms $(if $(1), -T $(2)) \
|
||||
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
|
||||
$(if $(KBUILD_PRESERVE),-p) \
|
||||
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
|
||||
|
||||
quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
|
||||
cmd_cc_symtypes_c = \
|
||||
$(call cmd_gensymtypes_c,true,$@) >/dev/null; \
|
||||
test -s $@ || rm -f $@
|
||||
|
||||
$(obj)/%.symtypes : $(src)/%.c FORCE
|
||||
$(call cmd,cc_symtypes_c)
|
||||
|
||||
# LLVM assembly
|
||||
# Generate .ll files from .c
|
||||
quiet_cmd_cc_ll_c = CC $(quiet_modtag) $@
|
||||
cmd_cc_ll_c = $(CC) $(c_flags) -emit-llvm -S -o $@ $<
|
||||
|
||||
$(obj)/%.ll: $(src)/%.c FORCE
|
||||
$(call if_changed_dep,cc_ll_c)
|
||||
|
||||
# C (.c) files
|
||||
# The C file is compiled and updated dependency information is generated.
|
||||
# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
|
||||
|
||||
quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
|
||||
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
|
||||
|
||||
ifdef CONFIG_MODVERSIONS
|
||||
# When module versioning is enabled the following steps are executed:
|
||||
# o compile a <file>.o from <file>.c
|
||||
# o if <file>.o doesn't contain a __ksymtab version, i.e. does
|
||||
# not export symbols, it's done.
|
||||
# o otherwise, we calculate symbol versions using the good old
|
||||
# genksyms on the preprocessed source and postprocess them in a way
|
||||
# that they are usable as a linker script
|
||||
# o generate .tmp_<file>.o from <file>.o using the linker to
|
||||
# replace the unresolved symbols __crc_exported_symbol with
|
||||
# the actual value of the checksum generated by genksyms
|
||||
# o remove .tmp_<file>.o to <file>.o
|
||||
|
||||
cmd_modversions_c = \
|
||||
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
|
||||
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
|
||||
> $(@D)/.tmp_$(@F:.o=.ver); \
|
||||
\
|
||||
$(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
|
||||
-T $(@D)/.tmp_$(@F:.o=.ver); \
|
||||
mv -f $(@D)/.tmp_$(@F) $@; \
|
||||
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
|
||||
fi
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
||||
ifndef CC_USING_RECORD_MCOUNT
|
||||
# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
|
||||
ifdef BUILD_C_RECORDMCOUNT
|
||||
ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
|
||||
RECORDMCOUNT_FLAGS = -w
|
||||
endif
|
||||
# Due to recursion, we must skip empty.o.
|
||||
# The empty.o file is created in the make process in order to determine
|
||||
# the target endianness and word size. It is made before all other C
|
||||
# files, including recordmcount.
|
||||
sub_cmd_record_mcount = \
|
||||
if [ $(@) != "scripts/mod/empty.o" ]; then \
|
||||
$(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \
|
||||
fi;
|
||||
recordmcount_source := $(srctree)/scripts/recordmcount.c \
|
||||
$(srctree)/scripts/recordmcount.h
|
||||
else
|
||||
sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
|
||||
"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
|
||||
"$(if $(CONFIG_64BIT),64,32)" \
|
||||
"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \
|
||||
"$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \
|
||||
"$(if $(part-of-module),1,0)" "$(@)";
|
||||
recordmcount_source := $(srctree)/scripts/recordmcount.pl
|
||||
endif # BUILD_C_RECORDMCOUNT
|
||||
cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \
|
||||
$(sub_cmd_record_mcount))
|
||||
endif # CC_USING_RECORD_MCOUNT
|
||||
endif # CONFIG_FTRACE_MCOUNT_RECORD
|
||||
|
||||
ifdef CONFIG_STACK_VALIDATION
|
||||
ifneq ($(SKIP_STACK_VALIDATION),1)
|
||||
|
||||
__objtool_obj := $(objtree)/tools/objtool/objtool
|
||||
|
||||
objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check)
|
||||
|
||||
objtool_args += $(if $(part-of-module), --module,)
|
||||
|
||||
ifndef CONFIG_FRAME_POINTER
|
||||
objtool_args += --no-fp
|
||||
endif
|
||||
ifdef CONFIG_GCOV_KERNEL
|
||||
objtool_args += --no-unreachable
|
||||
endif
|
||||
ifdef CONFIG_RETPOLINE
|
||||
objtool_args += --retpoline
|
||||
endif
|
||||
ifdef CONFIG_X86_SMAP
|
||||
objtool_args += --uaccess
|
||||
endif
|
||||
|
||||
# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
|
||||
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
|
||||
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
|
||||
cmd_objtool = $(if $(patsubst y%,, \
|
||||
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
|
||||
$(__objtool_obj) $(objtool_args) $@)
|
||||
objtool_obj = $(if $(patsubst y%,, \
|
||||
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
|
||||
$(__objtool_obj))
|
||||
|
||||
endif # SKIP_STACK_VALIDATION
|
||||
endif # CONFIG_STACK_VALIDATION
|
||||
|
||||
# Rebuild all objects when objtool changes, or is enabled/disabled.
|
||||
objtool_dep = $(objtool_obj) \
|
||||
$(wildcard include/config/orc/unwinder.h \
|
||||
include/config/stack/validation.h)
|
||||
|
||||
ifdef CONFIG_TRIM_UNUSED_KSYMS
|
||||
cmd_gen_ksymdeps = \
|
||||
$(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
|
||||
|
||||
# List module undefined symbols
|
||||
undefined_syms = $(NM) $< | $(AWK) '$$1 == "U" { printf("%s%s", x++ ? " " : "", $$2) }';
|
||||
endif
|
||||
|
||||
define rule_cc_o_c
|
||||
$(call cmd_and_fixdep,cc_o_c)
|
||||
$(call cmd,gen_ksymdeps)
|
||||
$(call cmd,checksrc)
|
||||
$(call cmd,checkdoc)
|
||||
$(call cmd,objtool)
|
||||
$(call cmd,modversions_c)
|
||||
$(call cmd,record_mcount)
|
||||
endef
|
||||
|
||||
define rule_as_o_S
|
||||
$(call cmd_and_fixdep,as_o_S)
|
||||
$(call cmd,gen_ksymdeps)
|
||||
$(call cmd,objtool)
|
||||
$(call cmd,modversions_S)
|
||||
endef
|
||||
|
||||
# Built-in and composite module parts
|
||||
$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
|
||||
$(call if_changed_rule,cc_o_c)
|
||||
$(call cmd,force_checksrc)
|
||||
|
||||
cmd_mod = { \
|
||||
echo $(if $($*-objs)$($*-y)$($*-m), $(addprefix $(obj)/, $($*-objs) $($*-y) $($*-m)), $(@:.mod=.o)); \
|
||||
$(undefined_syms) echo; \
|
||||
} > $@
|
||||
|
||||
$(obj)/%.mod: $(obj)/%.o FORCE
|
||||
$(call if_changed,mod)
|
||||
|
||||
quiet_cmd_cc_lst_c = MKLST $@
|
||||
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
|
||||
$(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
|
||||
System.map $(OBJDUMP) > $@
|
||||
|
||||
$(obj)/%.lst: $(src)/%.c FORCE
|
||||
$(call if_changed_dep,cc_lst_c)
|
||||
|
||||
# Compile assembler sources (.S)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# .S file exports must have their C prototypes defined in asm/asm-prototypes.h
|
||||
# or a file that it includes, in order to get versioned symbols. We build a
|
||||
# dummy C file that includes asm-prototypes and the EXPORT_SYMBOL lines from
|
||||
# the .S file (with trailing ';'), and run genksyms on that, to extract vers.
|
||||
#
|
||||
# This is convoluted. The .S file must first be preprocessed to run guards and
|
||||
# expand names, then the resulting exports must be constructed into plain
|
||||
# EXPORT_SYMBOL(symbol); to build our dummy C file, and that gets preprocessed
|
||||
# to make the genksyms input.
|
||||
#
|
||||
# These mirror gensymtypes_c and co above, keep them in synch.
|
||||
cmd_gensymtypes_S = \
|
||||
{ echo "\#include <linux/kernel.h>" ; \
|
||||
echo "\#include <asm/asm-prototypes.h>" ; \
|
||||
$(CPP) $(a_flags) $< | \
|
||||
grep "\<___EXPORT_SYMBOL\>" | \
|
||||
sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \
|
||||
$(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \
|
||||
scripts/genksyms/genksyms $(if $(1), -T $(2)) \
|
||||
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
|
||||
$(if $(KBUILD_PRESERVE),-p) \
|
||||
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
|
||||
|
||||
quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@
|
||||
cmd_cc_symtypes_S = \
|
||||
$(call cmd_gensymtypes_S,true,$@) >/dev/null; \
|
||||
test -s $@ || rm -f $@
|
||||
|
||||
$(obj)/%.symtypes : $(src)/%.S FORCE
|
||||
$(call cmd,cc_symtypes_S)
|
||||
|
||||
|
||||
quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@
|
||||
cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $<
|
||||
|
||||
$(obj)/%.s: $(src)/%.S FORCE
|
||||
$(call if_changed_dep,cpp_s_S)
|
||||
|
||||
quiet_cmd_as_o_S = AS $(quiet_modtag) $@
|
||||
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
|
||||
|
||||
ifdef CONFIG_ASM_MODVERSIONS
|
||||
|
||||
# versioning matches the C process described above, with difference that
|
||||
# we parse asm-prototypes.h C header to get function definitions.
|
||||
|
||||
cmd_modversions_S = \
|
||||
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
|
||||
$(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
|
||||
> $(@D)/.tmp_$(@F:.o=.ver); \
|
||||
\
|
||||
$(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
|
||||
-T $(@D)/.tmp_$(@F:.o=.ver); \
|
||||
mv -f $(@D)/.tmp_$(@F) $@; \
|
||||
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
|
||||
fi
|
||||
endif
|
||||
|
||||
$(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE
|
||||
$(call if_changed_rule,as_o_S)
|
||||
|
||||
targets += $(filter-out $(subdir-builtin), $(real-obj-y))
|
||||
targets += $(filter-out $(subdir-modorder), $(real-obj-m))
|
||||
targets += $(lib-y) $(always-y) $(MAKECMDGOALS)
|
||||
|
||||
# Linker scripts preprocessor (.lds.S -> .lds)
|
||||
# ---------------------------------------------------------------------------
|
||||
quiet_cmd_cpp_lds_S = LDS $@
|
||||
cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \
|
||||
-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
|
||||
|
||||
$(obj)/%.lds: $(src)/%.lds.S FORCE
|
||||
$(call if_changed_dep,cpp_lds_S)
|
||||
|
||||
# ASN.1 grammar
|
||||
# ---------------------------------------------------------------------------
|
||||
quiet_cmd_asn1_compiler = ASN.1 $(basename $@).[ch]
|
||||
cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
|
||||
$(basename $@).c $(basename $@).h
|
||||
|
||||
$(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
|
||||
$(call cmd,asn1_compiler)
|
||||
|
||||
# Build the compiled-in targets
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# To build objects in subdirs, we need to descend into the directories
|
||||
$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
|
||||
$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
|
||||
|
||||
#
|
||||
# Rule to compile a set of .o files into one .a file (without symbol table)
|
||||
#
|
||||
|
||||
quiet_cmd_ar_builtin = AR $@
|
||||
cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
|
||||
|
||||
$(obj)/built-in.a: $(real-obj-y) FORCE
|
||||
$(call if_changed,ar_builtin)
|
||||
|
||||
#
|
||||
# Rule to create modules.order file
|
||||
#
|
||||
# Create commands to either record .ko file or cat modules.order from
|
||||
# a subdirectory
|
||||
# Add $(obj-m) as the prerequisite to avoid updating the timestamp of
|
||||
# modules.order unless contained modules are updated.
|
||||
|
||||
cmd_modules_order = { $(foreach m, $(real-prereqs), \
|
||||
$(if $(filter %/modules.order, $m), cat $m, echo $(patsubst %.o,%.ko,$m));) :; } \
|
||||
| $(AWK) '!x[$$0]++' - > $@
|
||||
|
||||
$(obj)/modules.order: $(obj-m) FORCE
|
||||
$(call if_changed,modules_order)
|
||||
|
||||
#
|
||||
# Rule to compile a set of .o files into one .a file (with symbol table)
|
||||
#
|
||||
$(obj)/lib.a: $(lib-y) FORCE
|
||||
$(call if_changed,ar)
|
||||
|
||||
# NOTE:
|
||||
# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
|
||||
# module is turned into a multi object module, $^ will contain header file
|
||||
# dependencies recorded in the .*.cmd file.
|
||||
quiet_cmd_link_multi-m = LD [M] $@
|
||||
cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
|
||||
|
||||
$(multi-used-m): FORCE
|
||||
$(call if_changed,link_multi-m)
|
||||
$(call multi_depend, $(multi-used-m), .o, -objs -y -m)
|
||||
|
||||
targets += $(multi-used-m)
|
||||
targets := $(filter-out $(PHONY), $(targets))
|
||||
|
||||
# Add intermediate targets:
|
||||
# When building objects with specific suffix patterns, add intermediate
|
||||
# targets that the final targets are derived from.
|
||||
intermediate_targets = $(foreach sfx, $(2), \
|
||||
$(patsubst %$(strip $(1)),%$(sfx), \
|
||||
$(filter %$(strip $(1)), $(targets))))
|
||||
# %.asn1.o <- %.asn1.[ch] <- %.asn1
|
||||
# %.dtb.o <- %.dtb.S <- %.dtb <- %.dts
|
||||
# %.lex.o <- %.lex.c <- %.l
|
||||
# %.tab.o <- %.tab.[ch] <- %.y
|
||||
targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
|
||||
$(call intermediate_targets, .dtb.o, .dtb.S .dtb) \
|
||||
$(call intermediate_targets, .lex.o, .lex.c) \
|
||||
$(call intermediate_targets, .tab.o, .tab.c .tab.h)
|
||||
|
||||
# Build
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
ifdef single-build
|
||||
|
||||
KBUILD_SINGLE_TARGETS := $(filter $(obj)/%, $(KBUILD_SINGLE_TARGETS))
|
||||
|
||||
curdir-single := $(sort $(foreach x, $(KBUILD_SINGLE_TARGETS), \
|
||||
$(if $(filter $(x) $(basename $(x)).o, $(targets)), $(x))))
|
||||
|
||||
# Handle single targets without any rule: show "Nothing to be done for ..." or
|
||||
# "No rule to make target ..." depending on whether the target exists.
|
||||
unknown-single := $(filter-out $(addsuffix /%, $(subdir-ym)), \
|
||||
$(filter-out $(curdir-single), $(KBUILD_SINGLE_TARGETS)))
|
||||
|
||||
single-subdirs := $(foreach d, $(subdir-ym), \
|
||||
$(if $(filter $(d)/%, $(KBUILD_SINGLE_TARGETS)), $(d)))
|
||||
|
||||
__build: $(curdir-single) $(single-subdirs)
|
||||
ifneq ($(unknown-single),)
|
||||
$(Q)$(MAKE) -f /dev/null $(unknown-single)
|
||||
endif
|
||||
@:
|
||||
|
||||
ifeq ($(curdir-single),)
|
||||
# Nothing to do in this directory. Do not include any .*.cmd file for speed-up
|
||||
targets :=
|
||||
else
|
||||
targets += $(curdir-single)
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
__build: $(if $(KBUILD_BUILTIN), $(targets-for-builtin)) \
|
||||
$(if $(KBUILD_MODULES), $(targets-for-modules)) \
|
||||
$(subdir-ym) $(always-y)
|
||||
@:
|
||||
|
||||
endif
|
||||
|
||||
# Descending
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
PHONY += $(subdir-ym)
|
||||
$(subdir-ym):
|
||||
$(Q)$(MAKE) $(build)=$@ \
|
||||
$(if $(filter $@/, $(KBUILD_SINGLE_TARGETS)),single-build=) \
|
||||
need-builtin=$(if $(filter $@/built-in.a, $(subdir-builtin)),1) \
|
||||
need-modorder=$(if $(filter $@/modules.order, $(subdir-modorder)),1)
|
||||
|
||||
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
PHONY += FORCE
|
||||
|
||||
FORCE:
|
||||
|
||||
# Read all saved command lines and dependencies for the $(targets) we
|
||||
# may be building above, using $(if_changed{,_dep}). As an
|
||||
# optimization, we don't need to read them if the target does not
|
||||
# exist, we will rebuild anyway in that case.
|
||||
|
||||
existing-targets := $(wildcard $(sort $(targets)))
|
||||
|
||||
-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
|
||||
|
||||
# Create directories for object files if they do not exist
|
||||
obj-dirs := $(sort $(patsubst %/,%, $(dir $(targets))))
|
||||
# If targets exist, their directories apparently exist. Skip mkdir.
|
||||
existing-dirs := $(sort $(patsubst %/,%, $(dir $(existing-targets))))
|
||||
obj-dirs := $(strip $(filter-out $(existing-dirs), $(obj-dirs)))
|
||||
ifneq ($(obj-dirs),)
|
||||
$(shell mkdir -p $(obj-dirs))
|
||||
endif
|
||||
|
||||
.PHONY: $(PHONY)
|
||||
73
scripts/Makefile.clean
Normal file
73
scripts/Makefile.clean
Normal file
@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# ==========================================================================
|
||||
# Cleaning up
|
||||
# ==========================================================================
|
||||
|
||||
src := $(obj)
|
||||
|
||||
PHONY := __clean
|
||||
__clean:
|
||||
|
||||
include scripts/Kbuild.include
|
||||
|
||||
# The filename Kbuild has precedence over Makefile
|
||||
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
|
||||
include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
|
||||
|
||||
# Figure out what we need to build from the various variables
|
||||
# ==========================================================================
|
||||
|
||||
subdir-ymn := $(sort $(subdir-y) $(subdir-m) $(subdir-) \
|
||||
$(patsubst %/,%, $(filter %/, $(obj-y) $(obj-m) $(obj-))))
|
||||
|
||||
# Add subdir path
|
||||
|
||||
subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
|
||||
|
||||
# build a list of files to remove, usually relative to the current
|
||||
# directory
|
||||
|
||||
__clean-files := \
|
||||
$(clean-files) $(targets) $(hostprogs) $(userprogs) \
|
||||
$(extra-y) $(extra-m) $(extra-) \
|
||||
$(always-y) $(always-m) $(always-) \
|
||||
$(hostprogs-always-y) $(hostprogs-always-m) $(hostprogs-always-) \
|
||||
$(userprogs-always-y) $(userprogs-always-m) $(userprogs-always-)
|
||||
|
||||
# deprecated
|
||||
__clean-files += $(always) $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
|
||||
|
||||
__clean-files := $(filter-out $(no-clean-files), $(__clean-files))
|
||||
|
||||
# clean-files is given relative to the current directory, unless it
|
||||
# starts with $(objtree)/ (which means "./", so do not add "./" unless
|
||||
# you want to delete a file from the toplevel object directory).
|
||||
|
||||
__clean-files := $(wildcard \
|
||||
$(addprefix $(obj)/, $(filter-out $(objtree)/%, $(__clean-files))) \
|
||||
$(filter $(objtree)/%, $(__clean-files)))
|
||||
|
||||
# ==========================================================================
|
||||
|
||||
quiet_cmd_clean = CLEAN $(obj)
|
||||
cmd_clean = rm -rf $(__clean-files)
|
||||
|
||||
__clean: $(subdir-ymn)
|
||||
ifneq ($(strip $(__clean-files)),)
|
||||
$(call cmd,clean)
|
||||
endif
|
||||
@:
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# Generic stuff
|
||||
# ===========================================================================
|
||||
|
||||
# Descending
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
PHONY += $(subdir-ymn)
|
||||
$(subdir-ymn):
|
||||
$(Q)$(MAKE) $(clean)=$@
|
||||
|
||||
.PHONY: $(PHONY)
|
||||
4
scripts/kconfig/Kconfiglib/.gitignore
vendored
Normal file
4
scripts/kconfig/Kconfiglib/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.py[co]
|
||||
build/
|
||||
*.egg-info/
|
||||
dist/
|
||||
5
scripts/kconfig/Kconfiglib/LICENSE.txt
Normal file
5
scripts/kconfig/Kconfiglib/LICENSE.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Copyright (c) 2011-2019, Ulf Magnusson <ulfalizer@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
2
scripts/kconfig/Kconfiglib/MANIFEST.in
Normal file
2
scripts/kconfig/Kconfiglib/MANIFEST.in
Normal file
@ -0,0 +1,2 @@
|
||||
# Include the license file in source distributions
|
||||
include LICENSE.txt
|
||||
841
scripts/kconfig/Kconfiglib/README.rst
Normal file
841
scripts/kconfig/Kconfiglib/README.rst
Normal file
@ -0,0 +1,841 @@
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
|
||||
News
|
||||
----
|
||||
|
||||
Dependency loop with recent linux-next kernels
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To fix issues with dependency loops on recent linux-next kernels, apply `this
|
||||
patch <https://www.spinics.net/lists/linux-kbuild/msg23455.html>`_. Hopefully,
|
||||
it will be in ``linux-next`` soon.
|
||||
|
||||
``windows-curses`` is no longer automatically installed on Windows
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Starting with Kconfiglib 13.0.0, the `windows-curses
|
||||
<https://github.com/zephyrproject-rtos/windows-curses>`__ package is no longer
|
||||
automatically installed on Windows, and needs to be installed manually for the
|
||||
terminal ``menuconfig`` to work.
|
||||
|
||||
This fixes installation of Kconfiglib on MSYS2, which is not compatible with
|
||||
``windows-curses``. See `this issue
|
||||
<https://github.com/ulfalizer/Kconfiglib/issues/77>`__.
|
||||
|
||||
The ``menuconfig`` now shows a hint re. installing ``windows-curses`` when the
|
||||
``curses`` module can't be imported on Windows.
|
||||
|
||||
Sorry if this change caused problems!
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Kconfiglib is a `Kconfig
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-language.rst>`__
|
||||
implementation in Python 2/3. It started out as a helper library, but now has a
|
||||
enough functionality to also work well as a standalone Kconfig implementation
|
||||
(including `terminal and GUI menuconfig interfaces <Menuconfig interfaces_>`_
|
||||
and `Kconfig extensions`_).
|
||||
|
||||
The entire library is contained in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_. The
|
||||
bundled scripts are implemented on top of it. Implementing your own scripts
|
||||
should be relatively easy, if needed.
|
||||
|
||||
Kconfiglib is used exclusively by e.g. the `Zephyr
|
||||
<https://www.zephyrproject.org/>`__, `esp-idf
|
||||
<https://github.com/espressif/esp-idf>`__, and `ACRN
|
||||
<https://projectacrn.org/>`__ projects. It is also used for many small helper
|
||||
scripts in various projects.
|
||||
|
||||
Since Kconfiglib is based around a library, it can be used e.g. to generate a
|
||||
`Kconfig cross-reference
|
||||
<https://docs.zephyrproject.org/latest/reference/kconfig/index.html>`_, using
|
||||
the same robust Kconfig parser used for other Kconfig tools, instead of brittle
|
||||
ad-hoc parsing. The documentation generation script can be found `here
|
||||
<https://github.com/zephyrproject-rtos/zephyr/blob/master/doc/scripts/genrest.py>`__.
|
||||
|
||||
Kconfiglib implements the recently added `Kconfig preprocessor
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-macro-language.rst>`__.
|
||||
For backwards compatibility, environment variables can be referenced both as
|
||||
``$(FOO)`` (the new syntax) and as ``$FOO`` (the old syntax). The old syntax is
|
||||
deprecated, but will probably be supported for a long time, as it's needed to
|
||||
stay compatible with older Linux kernels. The major version will be increased
|
||||
if support is ever dropped. Using the old syntax with an undefined environment
|
||||
variable keeps the string as is.
|
||||
|
||||
Note: See `this issue <https://github.com/ulfalizer/Kconfiglib/issues/47>`__ if
|
||||
you run into a "macro expanded to blank string" error with kernel 4.18+.
|
||||
|
||||
See `this page
|
||||
<https://docs.zephyrproject.org/latest/guides/kconfig/tips.html>`__ for some
|
||||
Kconfig tips and best practices.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Installation with pip
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Kconfiglib is available on `PyPI <https://pypi.python.org/pypi/kconfiglib/>`_ and can be
|
||||
installed with e.g.
|
||||
|
||||
.. code::
|
||||
|
||||
$ pip(3) install kconfiglib
|
||||
|
||||
Microsoft Windows is supported.
|
||||
|
||||
The ``pip`` installation will give you both the base library and the following
|
||||
executables. All but two (``genconfig`` and ``setconfig``) mirror functionality
|
||||
available in the C tools.
|
||||
|
||||
- `menuconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_
|
||||
|
||||
- `guiconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/guiconfig.py>`_
|
||||
|
||||
- `oldconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/oldconfig.py>`_
|
||||
|
||||
- `olddefconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/olddefconfig.py>`_
|
||||
|
||||
- `savedefconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/savedefconfig.py>`_
|
||||
|
||||
- `defconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/defconfig.py>`_
|
||||
|
||||
- `alldefconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/alldefconfig.py>`_
|
||||
|
||||
- `allnoconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/allnoconfig.py>`_
|
||||
|
||||
- `allmodconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/allmodconfig.py>`_
|
||||
|
||||
- `allyesconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/allyesconfig.py>`_
|
||||
|
||||
- `listnewconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/listnewconfig.py>`_
|
||||
|
||||
- `genconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/genconfig.py>`_
|
||||
|
||||
- `setconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/setconfig.py>`_
|
||||
|
||||
``genconfig`` is intended to be run at build time. It generates a C header from
|
||||
the configuration and (optionally) information that can be used to rebuild only
|
||||
files that reference Kconfig symbols that have changed value.
|
||||
|
||||
Starting with Kconfiglib version 12.2.0, all utilities are compatible with both
|
||||
Python 2 and Python 3. Previously, ``menuconfig.py`` only ran under Python 3
|
||||
(i.e., it's now more backwards compatible than before).
|
||||
|
||||
**Note:** If you install Kconfiglib with ``pip``'s ``--user`` flag, make sure
|
||||
that your ``PATH`` includes the directory where the executables end up. You can
|
||||
list the installed files with ``pip(3) show -f kconfiglib``.
|
||||
|
||||
All releases have a corresponding tag in the git repository, e.g. ``v14.1.0``
|
||||
(the latest version).
|
||||
|
||||
`Semantic versioning <http://semver.org/>`_ is used. There's been ten small
|
||||
changes to the behavior of the API, a Windows packaging change, and a hashbang
|
||||
change to use ``python3``
|
||||
(`1 <https://github.com/ulfalizer/Kconfiglib/commit/e8b4ecb6ff6ccc1c7be0818314fbccda2ef2b2ee>`_,
|
||||
`2 <https://github.com/ulfalizer/Kconfiglib/commit/db633015a4d7b0ba1e882f665e191f350932b2af>`_,
|
||||
`3 <https://github.com/ulfalizer/Kconfiglib/commit/8983f7eb297dd614faf0beee3129559bc8ba338e>`_,
|
||||
`4 <https://github.com/ulfalizer/Kconfiglib/commit/cbf32e29a130d22bc734b7778e6304ac9df2a3e8>`_,
|
||||
`5 <https://github.com/ulfalizer/Kconfiglib/commit/eb6c21a9b33a2d6e2bed9882d4f930d0cab2f03b>`_,
|
||||
`6 <https://github.com/ulfalizer/Kconfiglib/commit/c19fc11355b13d75d97286402c7a933fb23d3b70>`_,
|
||||
`7 <https://github.com/ulfalizer/Kconfiglib/commit/7a428aa415606820a44291f475248b08e3952c4b>`_,
|
||||
`8 <https://github.com/ulfalizer/Kconfiglib/commit/f247ddf618ad29718e5efd3e69f8baf75d4d347b>`_,
|
||||
`9 <https://github.com/ulfalizer/Kconfiglib/commit/4fed39d9271ceb68be4157ab3f96a45b94f77dc0>`_,
|
||||
`10 <https://github.com/ulfalizer/Kconfiglib/commit/55bc8c380869ea663092212e8fe388ad7abae596>`_,
|
||||
`Windows packaging change <https://github.com/ulfalizer/Kconfiglib/commit/21b4c1e3b6e2867b9a0788d21a358f6b1f581d86>`_,
|
||||
`Python 3 hashbang change <https://github.com/ulfalizer/Kconfiglib/commit/9e0a8d29fa76adcb3f27bb2e20f16fefc2a8591e>`_),
|
||||
which is why the major version is at 14 rather than 2. I do major version bumps
|
||||
for all behavior changes, even tiny ones, and most of these were fixes for baby
|
||||
issues in the early days of the Kconfiglib 2 API.
|
||||
|
||||
Manual installation
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Just drop ``kconfiglib.py`` and the scripts you want somewhere. There are no
|
||||
third-party dependencies, but the terminal ``menuconfig`` won't work on Windows
|
||||
unless a package like `windows-curses
|
||||
<https://github.com/zephyrproject-rtos/windows-curses>`__ is installed.
|
||||
|
||||
Installation for the Linux kernel
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
See the module docstring at the top of `kconfiglib.py <https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_.
|
||||
|
||||
Python version compatibility (2.7/3.2+)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Kconfiglib and all utilities run under both Python 2.7 and Python 3.2 and
|
||||
later. The code mostly uses basic Python features and has no third-party
|
||||
dependencies, so keeping it backwards-compatible is pretty low effort.
|
||||
|
||||
The 3.2 requirement comes from ``argparse``. ``format()`` with unnumbered
|
||||
``{}`` is used as well.
|
||||
|
||||
A recent Python 3 version is recommended if you have a choice, as it'll give
|
||||
you better Unicode handling.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
1. `Install <Installation_>`_ the library and the utilities.
|
||||
|
||||
2. Write `Kconfig
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-language.rst>`__
|
||||
files that describe the available configuration options. See `this page
|
||||
<https://docs.zephyrproject.org/latest/guides/kconfig/tips.html>`__ for some
|
||||
general Kconfig advice.
|
||||
|
||||
3. Generate an initial configuration with e.g. ``menuconfig``/``guiconfig`` or
|
||||
``alldefconfig``. The configuration is saved as ``.config`` by default.
|
||||
|
||||
For more advanced projects, the ``defconfig`` utility can be used to
|
||||
generate the initial configuration from an existing configuration file.
|
||||
Usually, this existing configuration file would be a minimal configuration
|
||||
file, as generated by e.g. ``savedefconfig``.
|
||||
|
||||
4. Run ``genconfig`` to generate a header file. By default, it is saved as
|
||||
``config.h``.
|
||||
|
||||
Normally, ``genconfig`` would be run automatically as part of the build.
|
||||
|
||||
Before writing a header file or other configuration output, Kconfiglib
|
||||
compares the old contents of the file against the new contents. If there's
|
||||
no change, the write is skipped. This avoids updating file metadata like the
|
||||
modification time, and might save work depending on your build setup.
|
||||
|
||||
Adding new configuration output formats should be relatively straightforward.
|
||||
See the implementation of ``write_config()`` in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_.
|
||||
The documentation for the ``Symbol.config_string`` property has some tips as
|
||||
well.
|
||||
|
||||
5. To update an old ``.config`` file after the Kconfig files have changed (e.g.
|
||||
to add new options), run ``oldconfig`` (prompts for values for new options)
|
||||
or ``olddefconfig`` (gives new options their default value). Entering the
|
||||
``menuconfig`` or ``guiconfig`` interface and saving the configuration will
|
||||
also update it (the configuration interfaces always prompt for saving
|
||||
on exit if it would modify the contents of the ``.config`` file).
|
||||
|
||||
Due to Kconfig semantics, simply loading an old ``.config`` file performs an
|
||||
implicit ``olddefconfig``, so building will normally not be affected by
|
||||
having an outdated configuration.
|
||||
|
||||
Whenever ``.config`` is overwritten, the previous version of the file is saved
|
||||
to ``.config.old`` (or, more generally, to ``$KCONFIG_CONFIG.old``).
|
||||
|
||||
Using ``.config`` files as Make input
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``.config`` files use Make syntax and can be included directly in Makefiles to
|
||||
read configuration values from there. This is why ``n``-valued
|
||||
``bool``/``tristate`` values are written out as ``# CONFIG_FOO is not set`` (a
|
||||
Make comment) in ``.config``, allowing them to be tested with ``ifdef`` in
|
||||
Make.
|
||||
|
||||
If you make use of this, you might want to pass ``--config-out <filename>`` to
|
||||
``genconfig`` and include the configuration file it generates instead of
|
||||
including ``.config`` directly. This has the advantage that the generated
|
||||
configuration file will always be a "full" configuration file, even if
|
||||
``.config`` is outdated. Otherwise, it might be necessary to run
|
||||
``old(def)config`` or ``menuconfig``/``guiconfig`` before rebuilding with an
|
||||
outdated ``.config``.
|
||||
|
||||
If you use ``--sync-deps`` to generate incremental build information, you can
|
||||
include ``deps/auto.conf`` instead, which is also a full configuration file.
|
||||
|
||||
Useful helper macros
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The `include/linux/kconfig.h
|
||||
<https://github.com/torvalds/linux/blob/master/include/linux/kconfig.h>`_
|
||||
header in the Linux kernel defines some useful helper macros for testing
|
||||
Kconfig configuration values.
|
||||
|
||||
``IS_ENABLED()`` is generally useful, allowing configuration values to be
|
||||
tested in ``if`` statements with no runtime overhead.
|
||||
|
||||
Incremental building
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
See the docstring for ``Kconfig.sync_deps()`` in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_ for hints
|
||||
on implementing incremental builds (rebuilding just source files that reference
|
||||
changed configuration values).
|
||||
|
||||
Running the ``scripts/basic/fixdep.c`` tool from the kernel on the output of
|
||||
``gcc -MD <source file>`` might give you an idea of how it all fits together.
|
||||
|
||||
Library documentation
|
||||
---------------------
|
||||
|
||||
Kconfiglib comes with extensive documentation in the form of docstrings. To view it, run e.g.
|
||||
the following command:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
$ pydoc(3) kconfiglib
|
||||
|
||||
For HTML output, add ``-w``:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
$ pydoc(3) -w kconfiglib
|
||||
|
||||
This will also work after installing Kconfiglib with ``pip(3)``.
|
||||
|
||||
Documentation for other modules can be viewed in the same way (though a plain
|
||||
``--help`` will work when they're run as executables):
|
||||
|
||||
.. code:: sh
|
||||
|
||||
$ pydoc(3) menuconfig/guiconfig/...
|
||||
|
||||
A good starting point for learning the library is to read the module docstring
|
||||
(which you could also just read directly at the beginning of `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_). It
|
||||
gives an introduction to symbol values, the menu tree, and expressions.
|
||||
|
||||
After reading the module docstring, a good next step is to read the ``Kconfig``
|
||||
class documentation, and then the documentation for the ``Symbol``, ``Choice``,
|
||||
and ``MenuNode`` classes.
|
||||
|
||||
Please tell me if something is unclear or can be explained better.
|
||||
|
||||
Library features
|
||||
----------------
|
||||
|
||||
Kconfiglib can do the following, among other things:
|
||||
|
||||
- **Programmatically get and set symbol values**
|
||||
|
||||
See `allnoconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/allnoconfig.py>`_ and
|
||||
`allyesconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/allyesconfig.py>`_,
|
||||
which are automatically verified to produce identical output to the standard
|
||||
``make allnoconfig`` and ``make allyesconfig``.
|
||||
|
||||
- **Read and write .config and defconfig files**
|
||||
|
||||
The generated ``.config`` and ``defconfig`` (minimal configuration) files are
|
||||
character-for-character identical to what the C implementation would generate
|
||||
(except for the header comment). The test suite relies on this, as it
|
||||
compares the generated files.
|
||||
|
||||
- **Write C headers**
|
||||
|
||||
The generated headers use the same format as ``include/generated/autoconf.h``
|
||||
from the Linux kernel. Output for symbols appears in the order that they're
|
||||
defined, unlike in the C tools (where the order depends on the hash table
|
||||
implementation).
|
||||
|
||||
- **Implement incremental builds**
|
||||
|
||||
This uses the same scheme as the ``include/config`` directory in the kernel:
|
||||
Symbols are translated into files that are touched when the symbol's value
|
||||
changes between builds, which can be used to avoid having to do a full
|
||||
rebuild whenever the configuration is changed.
|
||||
|
||||
See the ``sync_deps()`` function for more information.
|
||||
|
||||
- **Inspect symbols**
|
||||
|
||||
Printing a symbol or other item (which calls ``__str__()``) returns its
|
||||
definition in Kconfig format. This also works for symbols defined in multiple
|
||||
locations.
|
||||
|
||||
A helpful ``__repr__()`` is on all objects too.
|
||||
|
||||
All ``__str__()`` and ``__repr__()`` methods are deliberately implemented
|
||||
with just public APIs, so all symbol information can be fetched separately as
|
||||
well.
|
||||
|
||||
- **Inspect expressions**
|
||||
|
||||
Expressions use a simple tuple-based format that can be processed manually
|
||||
if needed. Expression printing and evaluation functions are provided,
|
||||
implemented with public APIs.
|
||||
|
||||
- **Inspect the menu tree**
|
||||
|
||||
The underlying menu tree is exposed, including submenus created implicitly
|
||||
from symbols depending on preceding symbols. This can be used e.g. to
|
||||
implement menuconfig-like functionality.
|
||||
|
||||
See `menuconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_/`guiconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/guiconfig.py>`_ and the
|
||||
minimalistic `menuconfig_example.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/examples/menuconfig_example.py>`_
|
||||
example.
|
||||
|
||||
Kconfig extensions
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following Kconfig extensions are available:
|
||||
|
||||
- ``source`` supports glob patterns and includes each matching file. A pattern
|
||||
is required to match at least one file.
|
||||
|
||||
A separate ``osource`` statement is available for cases where it's okay for
|
||||
the pattern to match no files (in which case ``osource`` turns into a no-op).
|
||||
|
||||
- A relative ``source`` statement (``rsource``) is available, where file paths
|
||||
are specified relative to the directory of the current Kconfig file. An
|
||||
``orsource`` statement is available as well, analogous to ``osource``.
|
||||
|
||||
- Preprocessor user functions can be defined in Python, which makes it simple
|
||||
to integrate information from existing Python tools into Kconfig (e.g. to
|
||||
have Kconfig symbols depend on hardware information stored in some other
|
||||
format).
|
||||
|
||||
See the *Kconfig extensions* section in the
|
||||
`kconfiglib.py <https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_
|
||||
module docstring for more information.
|
||||
|
||||
- ``def_int``, ``def_hex``, and ``def_string`` are available in addition to
|
||||
``def_bool`` and ``def_tristate``, allowing ``int``, ``hex``, and ``string``
|
||||
symbols to be given a type and a default at the same time.
|
||||
|
||||
These can be useful in projects that make use of symbols defined in multiple
|
||||
locations, and remove some Kconfig inconsistency.
|
||||
|
||||
- Environment variables are expanded directly in e.g. ``source`` and
|
||||
``mainmenu`` statements, meaning ``option env`` symbols are redundant.
|
||||
|
||||
This is the standard behavior with the new `Kconfig preprocessor
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-macro-language.rst>`__,
|
||||
which Kconfiglib implements.
|
||||
|
||||
``option env`` symbols are accepted but ignored, which leads the caveat that
|
||||
they must have the same name as the environment variables they reference
|
||||
(Kconfiglib warns if the names differ). This keeps Kconfiglib compatible with
|
||||
older Linux kernels, where the name of the ``option env`` symbol always
|
||||
matched the environment variable. Compatibility with older Linux kernels is
|
||||
the main reason ``option env`` is still supported.
|
||||
|
||||
The C tools have dropped support for ``option env``.
|
||||
|
||||
- Two extra optional warnings can be enabled by setting environment variables,
|
||||
covering cases that are easily missed when making changes to Kconfig files:
|
||||
|
||||
* ``KCONFIG_WARN_UNDEF``: If set to ``y``, warnings will be generated for all
|
||||
references to undefined symbols within Kconfig files. The only gotcha is
|
||||
that all hex literals must be prefixed with ``0x`` or ``0X``, to make it
|
||||
possible to distinguish them from symbol references.
|
||||
|
||||
Some projects (e.g. the Linux kernel) use multiple Kconfig trees with many
|
||||
shared Kconfig files, leading to some safe undefined symbol references.
|
||||
``KCONFIG_WARN_UNDEF`` is useful in projects that only have a single
|
||||
Kconfig tree though.
|
||||
|
||||
``KCONFIG_STRICT`` is an older alias for this environment variable,
|
||||
supported for backwards compatibility.
|
||||
|
||||
* ``KCONFIG_WARN_UNDEF_ASSIGN``: If set to ``y``, warnings will be generated
|
||||
for all assignments to undefined symbols within ``.config`` files. By
|
||||
default, no such warnings are generated.
|
||||
|
||||
This warning can also be enabled/disabled by setting
|
||||
``Kconfig.warn_assign_undef`` to ``True``/``False``.
|
||||
|
||||
Other features
|
||||
--------------
|
||||
|
||||
- **Single-file implementation**
|
||||
|
||||
The entire library is contained in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_.
|
||||
|
||||
The tools implemented on top of it are one file each.
|
||||
|
||||
- **Robust and highly compatible with the C Kconfig tools**
|
||||
|
||||
The `test suite <https://github.com/ulfalizer/Kconfiglib/blob/master/testsuite.py>`_
|
||||
automatically compares output from Kconfiglib and the C tools
|
||||
by diffing the generated ``.config`` files for the real kernel Kconfig and
|
||||
defconfig files, for all ARCHes.
|
||||
|
||||
This currently involves comparing the output for 36 ARCHes and 498 defconfig
|
||||
files (or over 18000 ARCH/defconfig combinations in "obsessive" test suite
|
||||
mode). All tests are expected to pass.
|
||||
|
||||
A comprehensive suite of selftests is included as well.
|
||||
|
||||
- **Not horribly slow despite being a pure Python implementation**
|
||||
|
||||
The `allyesconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/allyesconfig.py>`_
|
||||
script currently runs in about 1.3 seconds on the Linux kernel on a Core i7
|
||||
2600K (with a warm file cache), including the ``make`` overhead from ``make
|
||||
scriptconfig``. Note that the Linux kernel Kconfigs are absolutely massive
|
||||
(over 14k symbols for x86) compared to most projects, and also have overhead
|
||||
from running shell commands via the Kconfig preprocessor.
|
||||
|
||||
Kconfiglib is especially speedy in cases where multiple ``.config`` files
|
||||
need to be processed, because the ``Kconfig`` files will only need to be parsed
|
||||
once.
|
||||
|
||||
For long-running jobs, `PyPy <https://pypy.org/>`_ gives a big performance
|
||||
boost. CPython is faster for short-running jobs as PyPy needs some time to
|
||||
warm up.
|
||||
|
||||
Kconfiglib also works well with the
|
||||
`multiprocessing <https://docs.python.org/3/library/multiprocessing.html>`_
|
||||
module. No global state is kept.
|
||||
|
||||
- **Generates more warnings than the C implementation**
|
||||
|
||||
Generates the same warnings as the C implementation, plus additional ones.
|
||||
Also detects dependency and ``source`` loops.
|
||||
|
||||
All warnings point out the location(s) in the ``Kconfig`` files where a
|
||||
symbol is defined, where applicable.
|
||||
|
||||
- **Unicode support**
|
||||
|
||||
Unicode characters in string literals in ``Kconfig`` and ``.config`` files are
|
||||
correctly handled. This support mostly comes for free from Python.
|
||||
|
||||
- **Windows support**
|
||||
|
||||
Nothing Linux-specific is used. Universal newlines mode is used for both
|
||||
Python 2 and Python 3.
|
||||
|
||||
The `Zephyr <https://www.zephyrproject.org/>`_ project uses Kconfiglib to
|
||||
generate ``.config`` files and C headers on Linux as well as Windows.
|
||||
|
||||
- **Internals that (mostly) mirror the C implementation**
|
||||
|
||||
While being simpler to understand and tweak.
|
||||
|
||||
Menuconfig interfaces
|
||||
---------------------
|
||||
|
||||
Three configuration interfaces are currently available:
|
||||
|
||||
- `menuconfig.py <https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_
|
||||
is a terminal-based configuration interface implemented using the standard
|
||||
Python ``curses`` module. ``xconfig`` features like showing invisible symbols and
|
||||
showing symbol names are included, and it's possible to jump directly to a symbol
|
||||
in the menu tree (even if it's currently invisible).
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/ulfalizer/Kconfiglib/screenshots/screenshots/menuconfig.gif
|
||||
|
||||
*There is now also a show-help mode that shows the help text of the currently
|
||||
selected symbol in the help window at the bottom.*
|
||||
|
||||
Starting with Kconfiglib 12.2.0, ``menuconfig.py`` runs under both Python 2
|
||||
and Python 3 (previously, it only ran under Python 3, so this was a
|
||||
backport). Running it under Python 3 provides better support for Unicode text
|
||||
entry (``get_wch()`` is not available in the ``curses`` module on Python 2).
|
||||
|
||||
There are no third-party dependencies on \*nix. On Windows,
|
||||
the ``curses`` modules is not available by default, but support
|
||||
can be added by installing the ``windows-curses`` package:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ pip install windows-curses
|
||||
|
||||
This uses wheels built from `this repository
|
||||
<https://github.com/zephyrproject-rtos/windows-curses>`_, which is in turn
|
||||
based on Christoph Gohlke's `Python Extension Packages for Windows
|
||||
<https://www.lfd.uci.edu/~gohlke/pythonlibs/#curses>`_.
|
||||
|
||||
See the docstring at the top of `menuconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_ for
|
||||
more information about the terminal menuconfig implementation.
|
||||
|
||||
- `guiconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/guiconfig.py>`_ is a
|
||||
graphical configuration interface written in `Tkinter
|
||||
<https://docs.python.org/3/library/tkinter.html>`_. Like ``menuconfig.py``,
|
||||
it supports showing all symbols (with invisible symbols in red) and jumping
|
||||
directly to symbols. Symbol values can also be changed directly from the
|
||||
jump-to dialog.
|
||||
|
||||
When single-menu mode is enabled, a single menu is shown at a time, like in
|
||||
the terminal menuconfig. Only this mode distinguishes between symbols defined
|
||||
with ``config`` and symbols defined with ``menuconfig``.
|
||||
|
||||
``guiconfig.py`` has been tested on X11, Windows, and macOS, and is
|
||||
compatible with both Python 2 and Python 3.
|
||||
|
||||
Despite being part of the Python standard library, ``tkinter`` often isn't
|
||||
included by default in Python installations on Linux. These commands will
|
||||
install it on a few different distributions:
|
||||
|
||||
- Ubuntu: ``sudo apt install python-tk``/``sudo apt install python3-tk``
|
||||
|
||||
- Fedora: ``dnf install python2-tkinter``/``dnf install python3-tkinter``
|
||||
|
||||
- Arch: ``sudo pacman -S tk``
|
||||
|
||||
- Clear Linux: ``sudo swupd bundle-add python3-tcl``
|
||||
|
||||
Screenshot below, with show-all mode enabled and the jump-to dialog open:
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/ulfalizer/Kconfiglib/screenshots/screenshots/guiconfig.png
|
||||
|
||||
To avoid having to carry around a bunch of GIFs, the image data is embedded
|
||||
in ``guiconfig.py``. To use separate GIF files instead, change
|
||||
``_USE_EMBEDDED_IMAGES`` to ``False`` in ``guiconfig.py``. The image files
|
||||
can be found in the `screenshots
|
||||
<https://github.com/ulfalizer/Kconfiglib/tree/screenshots/guiconfig>`_
|
||||
branch.
|
||||
|
||||
I did my best with the images, but some are definitely only art adjacent.
|
||||
Touch-ups are welcome. :)
|
||||
|
||||
- `pymenuconfig <https://github.com/RomaVis/pymenuconfig>`_, built by `RomaVis
|
||||
<https://github.com/RomaVis>`_, is an older portable Python 2/3 TkInter
|
||||
menuconfig implementation.
|
||||
|
||||
Screenshot below:
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/RomaVis/pymenuconfig/master/screenshot.PNG
|
||||
|
||||
While working on the terminal menuconfig implementation, I added a few APIs
|
||||
to Kconfiglib that turned out to be handy. ``pymenuconfig`` predates
|
||||
``menuconfig.py`` and ``guiconfig.py``, and so didn't have them available.
|
||||
Blame me for any workarounds.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Example scripts
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The `examples/ <https://github.com/ulfalizer/Kconfiglib/blob/master/examples>`_ directory contains some simple example scripts. Among these are the following ones. Make sure you run them with the latest version of Kconfiglib, as they might make use of newly added features.
|
||||
|
||||
- `eval_expr.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/eval_expr.py>`_ evaluates an expression in the context of a configuration.
|
||||
|
||||
- `find_symbol.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/find_symbol.py>`_ searches through expressions to find references to a symbol, also printing a "backtrace" with parents for each reference found.
|
||||
|
||||
- `help_grep.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/help_grep.py>`_ searches for a string in all help texts.
|
||||
|
||||
- `print_tree.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/print_tree.py>`_ prints a tree of all configuration items.
|
||||
|
||||
- `print_config_tree.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/print_config_tree.py>`_ is similar to ``print_tree.py``, but dumps the tree as it would appear in ``menuconfig``, including values. This can be handy for visually diffing between ``.config`` files and different versions of ``Kconfig`` files.
|
||||
|
||||
- `list_undefined.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/list_undefined.py>`_ finds references to symbols that are not defined by any architecture in the Linux kernel.
|
||||
|
||||
- `merge_config.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/merge_config.py>`_ merges configuration fragments to produce a complete .config, similarly to ``scripts/kconfig/merge_config.sh`` from the kernel.
|
||||
|
||||
- `menuconfig_example.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/menuconfig_example.py>`_ implements a configuration interface that uses notation similar to ``make menuconfig``. It's deliberately kept as simple as possible to demonstrate just the core concepts.
|
||||
|
||||
Real-world examples
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- `kconfig.py
|
||||
<https://github.com/zephyrproject-rtos/zephyr/blob/master/scripts/kconfig/kconfig.py>`_
|
||||
from the `Zephyr <https://www.zephyrproject.org/>`_ project handles
|
||||
``.config`` and header file generation, also doing configuration fragment
|
||||
merging
|
||||
|
||||
- `genrest.py
|
||||
<https://github.com/zephyrproject-rtos/zephyr/blob/master/doc/scripts/genrest.py>`_
|
||||
generates a Kconfig symbol cross-reference, which can be viewed `here
|
||||
<http://docs.zephyrproject.org/reference/kconfig/index.html>`__
|
||||
|
||||
- `CMake and IDE integration
|
||||
<https://github.com/espressif/esp-idf/tree/master/tools/kconfig_new>`_ from
|
||||
the ESP-IDF project, via a configuration server program.
|
||||
|
||||
- `A script for turning on USB-related options
|
||||
<https://github.com/google/syzkaller/blob/master/dashboard/config/kconfiglib-merge-usb-configs.py>`_,
|
||||
from the `syzkaller <https://github.com/google/syzkaller>`_ project.
|
||||
|
||||
- `Various automated checks
|
||||
<https://github.com/zephyrproject-rtos/ci-tools/blob/master/scripts/check_compliance.py>`_,
|
||||
including a check for references to undefined Kconfig symbols in source code.
|
||||
See the ``KconfigCheck`` class.
|
||||
|
||||
- `Various utilities
|
||||
<https://github.com/projectacrn/acrn-hypervisor/tree/master/scripts/kconfig>`_
|
||||
from the `ACRN <https://projectacrn.org/>`_ project
|
||||
|
||||
These use the older Kconfiglib 1 API, which was clunkier and not as general
|
||||
(functions instead of properties, no direct access to the menu structure or
|
||||
properties, uglier ``__str__()`` output):
|
||||
|
||||
- `genboardscfg.py <http://git.denx.de/?p=u-boot.git;a=blob;f=tools/genboardscfg.py;hb=HEAD>`_ from `Das U-Boot <http://www.denx.de/wiki/U-Boot>`_ generates some sort of legacy board database by pulling information from a newly added Kconfig-based configuration system (as far as I understand it :).
|
||||
|
||||
- `gen-manual-lists.py <https://git.busybox.net/buildroot/tree/support/scripts/gen-manual-lists.py?id=5676a2deea896f38123b99781da0a612865adeb0>`_ generated listings for an appendix in the `Buildroot <https://buildroot.org>`_ manual. (The listing has since been removed.)
|
||||
|
||||
- `gen_kconfig_doc.py <https://github.com/espressif/esp-idf/blob/master/docs/gen-kconfig-doc.py>`_ from the `esp-idf <https://github.com/espressif/esp-idf>`_ project generates documentation from Kconfig files.
|
||||
|
||||
- `SConf <https://github.com/CoryXie/SConf>`_ builds an interactive configuration interface (like ``menuconfig``) on top of Kconfiglib, for use e.g. with `SCons <scons.org>`_.
|
||||
|
||||
- `kconfig-diff.py <https://gist.github.com/dubiousjim/5638961>`_ -- a script by `dubiousjim <https://github.com/dubiousjim>`_ that compares kernel configurations.
|
||||
|
||||
- Originally, Kconfiglib was used in chapter 4 of my `master's thesis <http://liu.diva-portal.org/smash/get/diva2:473038/FULLTEXT01.pdf>`_ to automatically generate a "minimal" kernel for a given system. Parts of it bother me a bit now, but that's how it goes with old work.
|
||||
|
||||
Sample ``make iscriptconfig`` session
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following log should give some idea of the functionality available in the API:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make iscriptconfig
|
||||
A Kconfig instance 'kconf' for the architecture x86 has been created.
|
||||
>>> kconf # Calls Kconfig.__repr__()
|
||||
<configuration with 13711 symbols, main menu prompt "Linux/x86 4.14.0-rc7 Kernel Configuration", srctree ".", config symbol prefix "CONFIG_", warnings enabled, undef. symbol assignment warnings disabled>
|
||||
>>> kconf.mainmenu_text # Expanded main menu text
|
||||
'Linux/x86 4.14.0-rc7 Kernel Configuration'
|
||||
>>> kconf.top_node # The implicit top-level menu
|
||||
<menu node for menu, prompt "Linux/x86 4.14.0-rc7 Kernel Configuration" (visibility y), deps y, 'visible if' deps y, has child, Kconfig:5>
|
||||
>>> kconf.top_node.list # First child menu node
|
||||
<menu node for symbol SRCARCH, deps y, has next, Kconfig:7>
|
||||
>>> print(kconf.top_node.list) # Calls MenuNode.__str__()
|
||||
config SRCARCH
|
||||
string
|
||||
option env="SRCARCH"
|
||||
default "x86"
|
||||
>>> sym = kconf.top_node.list.next.item # Item contained in next menu node
|
||||
>>> print(sym) # Calls Symbol.__str__()
|
||||
config 64BIT
|
||||
bool "64-bit kernel" if ARCH = "x86"
|
||||
default ARCH != "i386"
|
||||
help
|
||||
Say yes to build a 64-bit kernel - formerly known as x86_64
|
||||
Say no to build a 32-bit kernel - formerly known as i386
|
||||
>>> sym # Calls Symbol.__repr__()
|
||||
<symbol 64BIT, bool, "64-bit kernel", value y, visibility y, direct deps y, arch/x86/Kconfig:2>
|
||||
>>> sym.assignable # Currently assignable values (0, 1, 2 = n, m, y)
|
||||
(0, 2)
|
||||
>>> sym.set_value(0) # Set it to n
|
||||
True
|
||||
>>> sym.tri_value # Check the new value
|
||||
0
|
||||
>>> sym = kconf.syms["X86_MPPARSE"] # Look up symbol by name
|
||||
>>> print(sym)
|
||||
config X86_MPPARSE
|
||||
bool "Enable MPS table" if (ACPI || SFI) && X86_LOCAL_APIC
|
||||
default y if X86_LOCAL_APIC
|
||||
help
|
||||
For old smp systems that do not have proper acpi support. Newer systems
|
||||
(esp with 64bit cpus) with acpi support, MADT and DSDT will override it
|
||||
>>> default = sym.defaults[0] # Fetch its first default
|
||||
>>> sym = default[1] # Fetch the default's condition (just a Symbol here)
|
||||
>>> print(sym)
|
||||
config X86_LOCAL_APIC
|
||||
bool
|
||||
default y
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
select PCI_MSI_IRQ_DOMAIN if PCI_MSI
|
||||
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
|
||||
>>> sym.nodes # Show the MenuNode(s) associated with it
|
||||
[<menu node for symbol X86_LOCAL_APIC, deps n, has next, arch/x86/Kconfig:1015>]
|
||||
>>> kconfiglib.expr_str(sym.defaults[0][1]) # Print the default's condition
|
||||
'X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI'
|
||||
>>> kconfiglib.expr_value(sym.defaults[0][1]) # Evaluate it (0 = n)
|
||||
0
|
||||
>>> kconf.syms["64BIT"].set_value(2)
|
||||
True
|
||||
>>> kconfiglib.expr_value(sym.defaults[0][1]) # Evaluate it again (2 = y)
|
||||
2
|
||||
>>> kconf.write_config("myconfig") # Save a .config
|
||||
>>> ^D
|
||||
$ cat myconfig
|
||||
# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_X86_64=y
|
||||
CONFIG_X86=y
|
||||
CONFIG_INSTRUCTION_DECODER=y
|
||||
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
|
||||
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
|
||||
CONFIG_LOCKDEP_SUPPORT=y
|
||||
CONFIG_STACKTRACE_SUPPORT=y
|
||||
CONFIG_MMU=y
|
||||
...
|
||||
|
||||
Test suite
|
||||
----------
|
||||
|
||||
The test suite is run with
|
||||
|
||||
.. code::
|
||||
|
||||
$ python(3) Kconfiglib/testsuite.py
|
||||
|
||||
`pypy <https://pypy.org/>`_ works too, and is much speedier for everything except ``allnoconfig.py``/``allnoconfig_simpler.py``/``allyesconfig.py``, where it doesn't have time to warm up since
|
||||
the scripts are run via ``make scriptconfig``.
|
||||
|
||||
The test suite must be run from the top-level kernel directory. It requires that the
|
||||
Kconfiglib git repository has been cloned into it and that the makefile patch has been applied.
|
||||
|
||||
To get rid of warnings generated for the kernel ``Kconfig`` files, add ``2>/dev/null`` to the command to
|
||||
discard ``stderr``.
|
||||
|
||||
**NOTE: Forgetting to apply the Makefile patch will cause some tests that compare generated configurations to fail**
|
||||
|
||||
**NOTE: The test suite overwrites .config in the kernel root, so make sure to back it up.**
|
||||
|
||||
The test suite consists of a set of selftests and a set of compatibility tests that
|
||||
compare configurations generated by Kconfiglib with
|
||||
configurations generated by the C tools, for a number of cases. See
|
||||
`testsuite.py <https://github.com/ulfalizer/Kconfiglib/blob/master/testsuite.py>`_
|
||||
for the available options.
|
||||
|
||||
The `tests/reltest <https://github.com/ulfalizer/Kconfiglib/blob/master/tests/reltest>`_ script runs the test suite
|
||||
and all the example scripts for both Python 2 and Python 3, verifying that everything works.
|
||||
|
||||
Rarely, the output from the C tools is changed slightly (most recently due to a
|
||||
`change <https://www.spinics.net/lists/linux-kbuild/msg17074.html>`_ I added).
|
||||
If you get test suite failures, try running the test suite again against the
|
||||
`linux-next tree <https://www.kernel.org/doc/man-pages/linux-next.html>`_,
|
||||
which has all the latest changes. I will make it clear if any
|
||||
non-backwards-compatible changes appear.
|
||||
|
||||
A lot of time is spent waiting around for ``make`` and the C utilities (which need to reparse all the
|
||||
Kconfig files for each defconfig test). Adding some multiprocessing to the test suite would make sense
|
||||
too.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
* This is version 2 of Kconfiglib, which is not backwards-compatible with
|
||||
Kconfiglib 1. A summary of changes between Kconfiglib 1 and Kconfiglib
|
||||
2 can be found `here
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/screenshots/kconfiglib-2-changes.txt>`__.
|
||||
|
||||
* I sometimes see people add custom output formats, which is pretty
|
||||
straightforward to do (see the implementations of ``write_autoconf()`` and
|
||||
``write_config()`` for a template, and also the documentation of the
|
||||
``Symbol.config_string`` property). If you come up with something you think
|
||||
might be useful to other people, I'm happy to take it in upstream. Batteries
|
||||
included and all that.
|
||||
|
||||
* Kconfiglib assumes the modules symbol is ``MODULES``, which is backwards-compatible.
|
||||
A warning is printed by default if ``option modules`` is set on some other symbol.
|
||||
|
||||
Let me know if you need proper ``option modules`` support. It wouldn't be that
|
||||
hard to add.
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
- To `RomaVis <https://github.com/RomaVis>`_, for making
|
||||
`pymenuconfig <https://github.com/RomaVis/pymenuconfig>`_ and suggesting
|
||||
the ``rsource`` keyword.
|
||||
|
||||
- To `Mitja Horvat <https://github.com/pinkfluid>`_, for adding support
|
||||
for user-defined styles to the terminal menuconfig.
|
||||
|
||||
- To `Philip Craig <https://github.com/philipc>`_ for adding
|
||||
support for the ``allnoconfig_y`` option and fixing an obscure issue
|
||||
with ``comment``\s inside ``choice``\s (that didn't affect correctness but
|
||||
made outputs differ). ``allnoconfig_y`` is used to force certain symbols
|
||||
to ``y`` during ``make allnoconfig`` to improve coverage.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
See `LICENSE.txt <https://github.com/ulfalizer/Kconfiglib/blob/master/LICENSE.txt>`_. SPDX license identifiers are used in the
|
||||
source code.
|
||||
27
scripts/kconfig/Kconfiglib/alldefconfig.py
Executable file
27
scripts/kconfig/Kconfiglib/alldefconfig.py
Executable file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where all symbols are set to their their default
|
||||
values.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed in
|
||||
the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/alldefconfig.py
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
kconf.load_allconfig("alldef.config")
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
46
scripts/kconfig/Kconfiglib/allmodconfig.py
Executable file
46
scripts/kconfig/Kconfiglib/allmodconfig.py
Executable file
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where as many symbols as possible are set to 'm'.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed
|
||||
in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/allmodconfig.py
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
|
||||
# See allnoconfig.py
|
||||
kconf.warn = False
|
||||
|
||||
for sym in kconf.unique_defined_syms:
|
||||
if sym.orig_type == kconfiglib.BOOL:
|
||||
# 'bool' choice symbols get their default value, as determined by
|
||||
# e.g. 'default's on the choice
|
||||
if not sym.choice:
|
||||
# All other bool symbols get set to 'y', like for allyesconfig
|
||||
sym.set_value(2)
|
||||
elif sym.orig_type == kconfiglib.TRISTATE:
|
||||
sym.set_value(1)
|
||||
|
||||
for choice in kconf.unique_choices:
|
||||
choice.set_value(2 if choice.orig_type == kconfiglib.BOOL else 1)
|
||||
|
||||
kconf.warn = True
|
||||
|
||||
kconf.load_allconfig("allmod.config")
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
45
scripts/kconfig/Kconfiglib/allnoconfig.py
Executable file
45
scripts/kconfig/Kconfiglib/allnoconfig.py
Executable file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where as many symbols as possible are set to 'n'.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed
|
||||
in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/allnoconfig.py
|
||||
"""
|
||||
|
||||
# See examples/allnoconfig_walk.py for another way to implement this script
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
|
||||
# Avoid warnings that would otherwise get printed by Kconfiglib for the
|
||||
# following:
|
||||
#
|
||||
# 1. Assigning a value to a symbol without a prompt, which never has any
|
||||
# effect
|
||||
#
|
||||
# 2. Assigning values invalid for the type (only bool/tristate symbols
|
||||
# accept 0/1/2, for n/m/y). The assignments will be ignored for other
|
||||
# symbol types, which is what we want.
|
||||
kconf.warn = False
|
||||
for sym in kconf.unique_defined_syms:
|
||||
sym.set_value(2 if sym.is_allnoconfig_y else 0)
|
||||
kconf.warn = True
|
||||
|
||||
kconf.load_allconfig("allno.config")
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
56
scripts/kconfig/Kconfiglib/allyesconfig.py
Executable file
56
scripts/kconfig/Kconfiglib/allyesconfig.py
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where as many symbols as possible are set to 'y'.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed
|
||||
in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/allyesconfig.py
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
|
||||
# See allnoconfig.py
|
||||
kconf.warn = False
|
||||
|
||||
# Try to set all symbols to 'y'. Dependencies might truncate the value down
|
||||
# later, but this will at least give the highest possible value.
|
||||
#
|
||||
# Assigning 0/1/2 to non-bool/tristate symbols has no effect (int/hex
|
||||
# symbols still take a string, because they preserve formatting).
|
||||
for sym in kconf.unique_defined_syms:
|
||||
# Set choice symbols to 'm'. This value will be ignored for choices in
|
||||
# 'y' mode (the "normal" mode), which will instead just get their
|
||||
# default selection, but will set all symbols in m-mode choices to 'm',
|
||||
# which is as high as they can go.
|
||||
#
|
||||
# Here's a convoluted example of how you might get an m-mode choice
|
||||
# even during allyesconfig:
|
||||
#
|
||||
# choice
|
||||
# tristate "weird choice"
|
||||
# depends on m
|
||||
sym.set_value(1 if sym.choice else 2)
|
||||
|
||||
# Set all choices to the highest possible mode
|
||||
for choice in kconf.unique_choices:
|
||||
choice.set_value(2)
|
||||
|
||||
kconf.warn = True
|
||||
|
||||
kconf.load_allconfig("allyes.config")
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
43
scripts/kconfig/Kconfiglib/defconfig.py
Executable file
43
scripts/kconfig/Kconfiglib/defconfig.py
Executable file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Reads a specified configuration file, then writes a new configuration file.
|
||||
This can be used to initialize the configuration from e.g. an arch-specific
|
||||
configuration file. This input configuration file would usually be a minimal
|
||||
configuration file, as generated by e.g. savedefconfig.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed in
|
||||
the KCONFIG_CONFIG environment variable.
|
||||
"""
|
||||
import argparse
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--kconfig",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
parser.add_argument(
|
||||
"config",
|
||||
metavar="CONFIGURATION",
|
||||
help="Input configuration file")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
print(kconf.load_config(args.config))
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
102
scripts/kconfig/Kconfiglib/examples/Kmenuconfig
Normal file
102
scripts/kconfig/Kconfiglib/examples/Kmenuconfig
Normal file
@ -0,0 +1,102 @@
|
||||
mainmenu "Example Kconfig configuration"
|
||||
|
||||
config MODULES
|
||||
bool "Enable loadable module support"
|
||||
option modules
|
||||
default y
|
||||
|
||||
menu "Bool and tristate symbols"
|
||||
|
||||
config BOOL
|
||||
bool "Bool symbol"
|
||||
default y
|
||||
|
||||
config BOOL_DEP
|
||||
bool "Dependent bool symbol"
|
||||
depends on BOOL
|
||||
|
||||
# Mix it up a bit with an 'if' instead of a 'depends on'
|
||||
if BOOL
|
||||
|
||||
config TRI_DEP
|
||||
tristate "Dependent tristate symbol"
|
||||
select SELECTED_BY_TRI_DEP
|
||||
imply IMPLIED_BY_TRI_DEP
|
||||
|
||||
endif
|
||||
|
||||
config TWO_MENU_NODES
|
||||
bool "First prompt"
|
||||
depends on BOOL
|
||||
|
||||
config TRI
|
||||
tristate "Tristate symbol"
|
||||
|
||||
config TWO_MENU_NODES
|
||||
bool "Second prompt"
|
||||
|
||||
comment "These are selected by TRI_DEP"
|
||||
|
||||
config SELECTED_BY_TRI_DEP
|
||||
tristate "Tristate selected by TRI_DEP"
|
||||
|
||||
config IMPLIED_BY_TRI_DEP
|
||||
tristate "Tristate implied by TRI_DEP"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
menu "String, int, and hex symbols"
|
||||
|
||||
config STRING
|
||||
string "String symbol"
|
||||
default "foo"
|
||||
|
||||
config INT
|
||||
int "Int symbol"
|
||||
default 747
|
||||
|
||||
config HEX
|
||||
hex "Hex symbol"
|
||||
default 0xABC
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
menu "Various choices"
|
||||
|
||||
choice BOOL_CHOICE
|
||||
bool "Bool choice"
|
||||
|
||||
config BOOL_CHOICE_SYM_1
|
||||
bool "Bool choice sym 1"
|
||||
|
||||
config BOOL_CHOICE_SYM_2
|
||||
bool "Bool choice sym 2"
|
||||
|
||||
endchoice
|
||||
|
||||
choice TRI_CHOICE
|
||||
tristate "Tristate choice"
|
||||
|
||||
config TRI_CHOICE_SYM_1
|
||||
tristate "Tristate choice sym 1"
|
||||
|
||||
config TRI_CHOICE_SYM_2
|
||||
tristate "Tristate choice sym 2"
|
||||
|
||||
endchoice
|
||||
|
||||
choice OPT_BOOL_CHOICE
|
||||
bool "Optional bool choice"
|
||||
optional
|
||||
|
||||
config OPT_BOOL_CHOICE_SYM_1
|
||||
bool "Optional bool choice sym 1"
|
||||
|
||||
config OPT_BOOL_CHOICE_SYM_2
|
||||
bool "Optional bool choice sym 2"
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
66
scripts/kconfig/Kconfiglib/examples/allnoconfig_walk.py
Normal file
66
scripts/kconfig/Kconfiglib/examples/allnoconfig_walk.py
Normal file
@ -0,0 +1,66 @@
|
||||
# This is tree-walking version of allnoconfig.py, for demonstration purposes.
|
||||
# Verified by the test suite to generate identical output to 'make allnoconfig'
|
||||
# for all ARCHes.
|
||||
#
|
||||
# Note: A more practical version would use Kconfig.node_iter(). The manual tree
|
||||
# walking is for demonstration purposes.
|
||||
#
|
||||
# Usage for the Linux kernel:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig_walk.py
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, Symbol
|
||||
|
||||
|
||||
def do_allnoconfig(node):
|
||||
global changed
|
||||
|
||||
# Walk the tree of menu nodes. You can imagine this as going down/into menu
|
||||
# entries in the menuconfig interface, setting each to n (or the lowest
|
||||
# assignable value).
|
||||
|
||||
while node:
|
||||
if isinstance(node.item, Symbol):
|
||||
sym = node.item
|
||||
|
||||
# Is the symbol a non-allnoconfig_y symbol that can be set to a
|
||||
# lower value than its current value?
|
||||
if (not sym.is_allnoconfig_y and
|
||||
sym.assignable and
|
||||
sym.assignable[0] < sym.tri_value):
|
||||
|
||||
# Yup, lower it
|
||||
sym.set_value(sym.assignable[0])
|
||||
changed = True
|
||||
|
||||
# Recursively lower children
|
||||
if node.list:
|
||||
do_allnoconfig(node.list)
|
||||
|
||||
node = node.next
|
||||
|
||||
|
||||
# Parse the Kconfig files
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
|
||||
# Do an initial pass to set 'option allnoconfig_y' symbols to y
|
||||
for sym in kconf.unique_defined_syms:
|
||||
if sym.is_allnoconfig_y:
|
||||
sym.set_value(2)
|
||||
|
||||
while True:
|
||||
# Changing later symbols in the configuration can sometimes allow earlier
|
||||
# symbols to be lowered, e.g. if a later symbol 'select's an earlier
|
||||
# symbol. To handle such situations, we do additional passes over the tree
|
||||
# until we're no longer able to change the value of any symbol in a pass.
|
||||
changed = False
|
||||
|
||||
do_allnoconfig(kconf.top_node)
|
||||
|
||||
# Did the pass change any symbols?
|
||||
if not changed:
|
||||
break
|
||||
|
||||
print(kconf.write_config())
|
||||
39
scripts/kconfig/Kconfiglib/examples/defconfig_oldconfig.py
Normal file
39
scripts/kconfig/Kconfiglib/examples/defconfig_oldconfig.py
Normal file
@ -0,0 +1,39 @@
|
||||
# Produces exactly the same output as the following script:
|
||||
#
|
||||
# make defconfig
|
||||
# echo CONFIG_ETHERNET=n >> .config
|
||||
# make oldconfig
|
||||
# echo CONFIG_ETHERNET=y >> .config
|
||||
# yes n | make oldconfig
|
||||
#
|
||||
# This came up in https://github.com/ulfalizer/Kconfiglib/issues/15.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/defconfig_oldconfig.py
|
||||
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
kconf = kconfiglib.Kconfig(sys.argv[1])
|
||||
|
||||
# Mirrors defconfig
|
||||
kconf.load_config("arch/x86/configs/x86_64_defconfig")
|
||||
kconf.write_config()
|
||||
|
||||
# Mirrors the first oldconfig
|
||||
kconf.load_config()
|
||||
kconf.syms["ETHERNET"].set_value(0)
|
||||
kconf.write_config()
|
||||
|
||||
# Mirrors the second oldconfig
|
||||
kconf.load_config()
|
||||
kconf.syms["ETHERNET"].set_value(2)
|
||||
for s in kconf.unique_defined_syms:
|
||||
if s.user_value is None and 0 in s.assignable:
|
||||
s.set_value(0)
|
||||
|
||||
# Write the final configuration
|
||||
print(kconf.write_config())
|
||||
15
scripts/kconfig/Kconfiglib/examples/dumpvars.py
Normal file
15
scripts/kconfig/Kconfiglib/examples/dumpvars.py
Normal file
@ -0,0 +1,15 @@
|
||||
# Prints all (set) environment variables referenced in the Kconfig files
|
||||
# together with their values, as a list of assignments.
|
||||
#
|
||||
# Note: This only works for environment variables referenced via the $(FOO)
|
||||
# preprocessor syntax. The older $FOO syntax is maintained for backwards
|
||||
# compatibility.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
print(" ".join("{}='{}'".format(var, os.environ[var])
|
||||
for var in kconfiglib.Kconfig(sys.argv[1]).env_vars))
|
||||
24
scripts/kconfig/Kconfiglib/examples/eval_expr.py
Normal file
24
scripts/kconfig/Kconfiglib/examples/eval_expr.py
Normal file
@ -0,0 +1,24 @@
|
||||
# Evaluates an expression (e.g. "X86_64 || (X86_32 && X86_LOCAL_APIC)") in the
|
||||
# context of a configuration. Note that this always yields a tristate value (n,
|
||||
# m, or y).
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/eval_expr.py SCRIPT_ARG=<expr>
|
||||
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit("Pass the expression to evaluate with SCRIPT_ARG=<expression>")
|
||||
|
||||
kconf = kconfiglib.Kconfig(sys.argv[1])
|
||||
expr = sys.argv[2]
|
||||
|
||||
# Enable modules so that m doesn't get demoted to n
|
||||
kconf.modules.set_value(2)
|
||||
|
||||
print("the expression '{}' evaluates to {}"
|
||||
.format(expr, kconf.eval_string(expr)))
|
||||
112
scripts/kconfig/Kconfiglib/examples/find_symbol.py
Normal file
112
scripts/kconfig/Kconfiglib/examples/find_symbol.py
Normal file
@ -0,0 +1,112 @@
|
||||
# Prints all menu nodes that reference a given symbol any of their properties
|
||||
# or property conditions, along with their parent menu nodes.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/find_symbol.py SCRIPT_ARG=<name>
|
||||
#
|
||||
# Example output for SCRIPT_ARG=X86:
|
||||
#
|
||||
# Found 470 locations that reference X86:
|
||||
#
|
||||
# ========== Location 1 (init/Kconfig:1108) ==========
|
||||
#
|
||||
# config SGETMASK_SYSCALL
|
||||
# bool
|
||||
# prompt "sgetmask/ssetmask syscalls support" if EXPERT
|
||||
# default PARISC || M68K || PPC || MIPS || X86 || SPARC || MICROBLAZE || SUPERH
|
||||
# help
|
||||
# sys_sgetmask and sys_ssetmask are obsolete system calls
|
||||
# no longer supported in libc but still enabled by default in some
|
||||
# architectures.
|
||||
#
|
||||
# If unsure, leave the default option here.
|
||||
#
|
||||
# ---------- Parent 1 (init/Kconfig:1077) ----------
|
||||
#
|
||||
# menuconfig EXPERT
|
||||
# bool
|
||||
# prompt "Configure standard kernel features (expert users)"
|
||||
# select DEBUG_KERNEL
|
||||
# help
|
||||
# This option allows certain base kernel options and settings
|
||||
# to be disabled or tweaked. This is for specialized
|
||||
# environments which can tolerate a "non-standard" kernel.
|
||||
# Only use this if you really know what you are doing.
|
||||
#
|
||||
# ---------- Parent 2 (init/Kconfig:39) ----------
|
||||
#
|
||||
# menu "General setup"
|
||||
#
|
||||
# ========== Location 2 (arch/Kconfig:29) ==========
|
||||
#
|
||||
# config OPROFILE_EVENT_MULTIPLEX
|
||||
# bool
|
||||
# prompt "OProfile multiplexing support (EXPERIMENTAL)"
|
||||
# default "n"
|
||||
# depends on OPROFILE && X86
|
||||
# help
|
||||
# The number of hardware counters is limited. The multiplexing
|
||||
# feature enables OProfile to gather more events than counters
|
||||
# are provided by the hardware. This is realized by switching
|
||||
# between events at a user specified time interval.
|
||||
#
|
||||
# If unsure, say N.
|
||||
#
|
||||
# ---------- Parent 1 (arch/Kconfig:16) ----------
|
||||
#
|
||||
# config OPROFILE
|
||||
# tristate
|
||||
# prompt "OProfile system profiling"
|
||||
# select RING_BUFFER
|
||||
# select RING_BUFFER_ALLOW_SWAP
|
||||
# depends on PROFILING && HAVE_OPROFILE
|
||||
# help
|
||||
# OProfile is a profiling system capable of profiling the
|
||||
# whole system, include the kernel, kernel modules, libraries,
|
||||
# and applications.
|
||||
#
|
||||
# If unsure, say N.
|
||||
#
|
||||
# ---------- Parent 2 (init/Kconfig:39) ----------
|
||||
#
|
||||
# menu "General setup"
|
||||
#
|
||||
# ... (tons more)
|
||||
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=<name>')
|
||||
|
||||
kconf = kconfiglib.Kconfig(sys.argv[1])
|
||||
sym_name = sys.argv[2]
|
||||
if sym_name not in kconf.syms:
|
||||
print("No symbol {} exists in the configuration".format(sym_name))
|
||||
sys.exit(0)
|
||||
|
||||
referencing = [node for node in kconf.node_iter()
|
||||
if kconf.syms[sym_name] in node.referenced]
|
||||
if not referencing:
|
||||
print("No references to {} found".format(sym_name))
|
||||
sys.exit(0)
|
||||
|
||||
print("Found {} locations that reference {}:\n"
|
||||
.format(len(referencing), sym_name))
|
||||
|
||||
for i, node in enumerate(referencing, 1):
|
||||
print("========== Location {} ({}:{}) ==========\n\n{}"
|
||||
.format(i, node.filename, node.linenr, node))
|
||||
|
||||
# Print the parents of the menu node too
|
||||
|
||||
node = node.parent
|
||||
parent_i = 1
|
||||
while node is not kconf.top_node:
|
||||
print("---------- Parent {} ({}:{}) ----------\n\n{}"
|
||||
.format(parent_i, node.filename, node.linenr, node))
|
||||
node = node.parent
|
||||
parent_i += 1
|
||||
64
scripts/kconfig/Kconfiglib/examples/help_grep.py
Normal file
64
scripts/kconfig/Kconfiglib/examples/help_grep.py
Normal file
@ -0,0 +1,64 @@
|
||||
# Does a case-insensitive search for a regular expression in the help texts of
|
||||
# symbols and choices and the prompts of menus and comments. Prints the
|
||||
# matching items together with their locations and the matching text.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=<regex>
|
||||
#
|
||||
# Shortened example output for SCRIPT_ARG=general:
|
||||
#
|
||||
# menu "General setup"
|
||||
# location: init/Kconfig:39
|
||||
#
|
||||
# config SYSVIPC
|
||||
# bool
|
||||
# prompt "System V IPC"
|
||||
# help
|
||||
# ...
|
||||
# exchange information. It is generally considered to be a good thing,
|
||||
# ...
|
||||
#
|
||||
# location: init/Kconfig:233
|
||||
#
|
||||
# config BSD_PROCESS_ACCT
|
||||
# bool
|
||||
# prompt "BSD Process Accounting" if MULTIUSER
|
||||
# help
|
||||
# ...
|
||||
# information. This is generally a good idea, so say Y.
|
||||
#
|
||||
# location: init/Kconfig:403
|
||||
#
|
||||
# ...
|
||||
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, Symbol, Choice, MENU, COMMENT
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit("Pass the regex with SCRIPT_ARG=<regex>")
|
||||
|
||||
search = re.compile(sys.argv[2], re.IGNORECASE).search
|
||||
|
||||
for node in Kconfig(sys.argv[1]).node_iter():
|
||||
match = False
|
||||
|
||||
if isinstance(node.item, (Symbol, Choice)) and \
|
||||
node.help is not None and search(node.help):
|
||||
print(node.item)
|
||||
match = True
|
||||
|
||||
elif node.item == MENU and search(node.prompt[0]):
|
||||
print('menu "{}"'.format(node.prompt[0]))
|
||||
match = True
|
||||
|
||||
elif node.item == COMMENT and search(node.prompt[0]):
|
||||
print('comment "{}"'.format(node.prompt[0]))
|
||||
match = True
|
||||
|
||||
if match:
|
||||
print("location: {}:{}\n".format(node.filename, node.linenr))
|
||||
1
scripts/kconfig/Kconfiglib/examples/kconfiglib.py
Symbolic link
1
scripts/kconfig/Kconfiglib/examples/kconfiglib.py
Symbolic link
@ -0,0 +1 @@
|
||||
../kconfiglib.py
|
||||
156
scripts/kconfig/Kconfiglib/examples/list_undefined.py
Normal file
156
scripts/kconfig/Kconfiglib/examples/list_undefined.py
Normal file
@ -0,0 +1,156 @@
|
||||
# Prints a list of symbols that are referenced in the Kconfig files of some
|
||||
# architecture but not defined by the Kconfig files of any architecture.
|
||||
#
|
||||
# A Kconfig file might be shared between many architectures and legitimately
|
||||
# reference undefined symbols for some of them, but if no architecture defines
|
||||
# the symbol, it usually indicates a problem or potential cleanup.
|
||||
#
|
||||
# This script could be sped up a lot if needed. See the comment near the
|
||||
# referencing_nodes() call.
|
||||
#
|
||||
# Run with the following command in the kernel root:
|
||||
#
|
||||
# $ python(3) Kconfiglib/examples/list_undefined.py
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# Registering defined and undefined symbols for all arches
|
||||
# Processing mips
|
||||
# Processing ia64
|
||||
# Processing metag
|
||||
# ...
|
||||
#
|
||||
# Finding references to each undefined symbol
|
||||
# Processing mips
|
||||
# Processing ia64
|
||||
# Processing metag
|
||||
# ...
|
||||
#
|
||||
# The following globally undefined symbols were found, listed here
|
||||
# together with the locations of the items that reference them.
|
||||
# References might come from enclosing menus and ifs.
|
||||
#
|
||||
# ARM_ERRATA_753970: arch/arm/mach-mvebu/Kconfig:56, arch/arm/mach-mvebu/Kconfig:39
|
||||
# SUNXI_CCU_MP: drivers/clk/sunxi-ng/Kconfig:14
|
||||
# SUNXI_CCU_DIV: drivers/clk/sunxi-ng/Kconfig:14
|
||||
# AC97: sound/ac97/Kconfig:6
|
||||
# ...
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from kconfiglib import Kconfig
|
||||
|
||||
|
||||
# Referenced inside the Kconfig files
|
||||
os.environ["KERNELVERSION"] = str(
|
||||
subprocess.check_output(("make", "kernelversion")).decode("utf-8").rstrip()
|
||||
)
|
||||
|
||||
|
||||
def all_arch_srcarch_pairs():
|
||||
"""
|
||||
Generates all valid (ARCH, SRCARCH) tuples for the kernel, corresponding to
|
||||
different architectures. SRCARCH holds the arch/ subdirectory.
|
||||
"""
|
||||
for srcarch in os.listdir("arch"):
|
||||
# Each subdirectory of arch/ containing a Kconfig file corresponds to
|
||||
# an architecture
|
||||
if os.path.exists(os.path.join("arch", srcarch, "Kconfig")):
|
||||
yield (srcarch, srcarch)
|
||||
|
||||
# Some architectures define additional ARCH settings with ARCH != SRCARCH
|
||||
# (search for "Additional ARCH settings for" in the top-level Makefile)
|
||||
|
||||
yield ("i386", "x86")
|
||||
yield ("x86_64", "x86")
|
||||
|
||||
yield ("sparc32", "sparc")
|
||||
yield ("sparc64", "sparc")
|
||||
|
||||
yield ("sh64", "sh")
|
||||
|
||||
yield ("um", "um")
|
||||
|
||||
|
||||
def all_arch_srcarch_kconfigs():
|
||||
"""
|
||||
Generates Kconfig instances for all the architectures in the kernel
|
||||
"""
|
||||
|
||||
os.environ["srctree"] = "."
|
||||
os.environ["HOSTCC"] = "gcc"
|
||||
os.environ["HOSTCXX"] = "g++"
|
||||
os.environ["CC"] = "gcc"
|
||||
os.environ["LD"] = "ld"
|
||||
|
||||
for arch, srcarch in all_arch_srcarch_pairs():
|
||||
print(" Processing " + arch)
|
||||
|
||||
os.environ["ARCH"] = arch
|
||||
os.environ["SRCARCH"] = srcarch
|
||||
|
||||
# um (User Mode Linux) uses a different base Kconfig file
|
||||
yield Kconfig("Kconfig" if arch != "um" else "arch/x86/um/Kconfig",
|
||||
warn=False)
|
||||
|
||||
|
||||
print("Registering defined and undefined symbols for all arches")
|
||||
|
||||
# Sets holding the names of all defined and undefined symbols, for all
|
||||
# architectures
|
||||
defined = set()
|
||||
undefined = set()
|
||||
|
||||
for kconf in all_arch_srcarch_kconfigs():
|
||||
for name, sym in kconf.syms.items():
|
||||
if sym.nodes:
|
||||
# If the symbol has a menu node, it is defined
|
||||
defined.add(name)
|
||||
else:
|
||||
# Undefined symbol. We skip some of the uninteresting ones.
|
||||
|
||||
# Due to how Kconfig works, integer literals show up as symbols
|
||||
# (from e.g. 'default 1'). Skip those.
|
||||
try:
|
||||
int(name, 0)
|
||||
continue
|
||||
except ValueError:
|
||||
# Interesting undefined symbol
|
||||
undefined.add(name)
|
||||
|
||||
|
||||
print("\nFinding references to each undefined symbol")
|
||||
|
||||
def referencing_nodes(kconf, name):
|
||||
# Returns a list of all menu nodes that reference a symbol named 'name' in
|
||||
# any of their properties or property conditions
|
||||
res = []
|
||||
|
||||
for node in kconf.node_iter():
|
||||
for ref in node.referenced:
|
||||
if ref.name == name:
|
||||
res.append(node)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
# Maps each globally undefined symbol to the menu nodes that reference it
|
||||
undef_sym_refs = [(name, set()) for name in undefined - defined]
|
||||
|
||||
for kconf in all_arch_srcarch_kconfigs():
|
||||
for name, refs in undef_sym_refs:
|
||||
# This means that we search the entire configuration tree for each
|
||||
# undefined symbol, which is terribly inefficient. We could speed
|
||||
# things up by tweaking referencing_nodes() to compare each symbol to
|
||||
# multiple symbols while walking the configuration tree.
|
||||
for node in referencing_nodes(kconf, name):
|
||||
refs.add("{}:{}".format(node.filename, node.linenr))
|
||||
|
||||
|
||||
print("\nThe following globally undefined symbols were found, listed here\n"
|
||||
"together with the locations of the items that reference them.\n"
|
||||
"References might come from enclosing menus and ifs.\n")
|
||||
|
||||
for name, refs in undef_sym_refs:
|
||||
print(" {}: {}".format(name, ", ".join(refs)))
|
||||
341
scripts/kconfig/Kconfiglib/examples/menuconfig_example.py
Executable file
341
scripts/kconfig/Kconfiglib/examples/menuconfig_example.py
Executable file
@ -0,0 +1,341 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Implements a simple configuration interface on top of Kconfiglib to
|
||||
# demonstrate concepts for building a menuconfig-like. Emulates how the
|
||||
# standard menuconfig prints menu entries.
|
||||
#
|
||||
# Always displays the entire Kconfig tree to keep things as simple as possible
|
||||
# (all symbols, choices, menus, and comments).
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ python(3) Kconfiglib/examples/menuconfig.py <Kconfig file>
|
||||
#
|
||||
# A sample Kconfig is available in Kconfiglib/examples/Kmenuconfig.
|
||||
#
|
||||
# Here's a notation guide. The notation matches the one used by menuconfig
|
||||
# (scripts/kconfig/mconf):
|
||||
#
|
||||
# [ ] prompt - Bool
|
||||
# < > prompt - Tristate
|
||||
# {M} prompt - Tristate selected to m. Can only be set to m or y.
|
||||
# -*- prompt - Bool/tristate selected to y, pinning it
|
||||
# -M- prompt - Tristate selected to m that also has m visibility,
|
||||
# pinning it to m
|
||||
# (foo) prompt - String/int/hex symbol with value "foo"
|
||||
# --> prompt - The selected symbol in a choice in y mode. This
|
||||
# syntax is unique to this example.
|
||||
#
|
||||
# When modules are disabled, the .type attribute of TRISTATE symbols and
|
||||
# choices automatically changes to BOOL. This trick is used by the C
|
||||
# implementation as well, and gives the expected behavior without having to do
|
||||
# anything extra here. The original type is available in .orig_type if needed.
|
||||
#
|
||||
# The Kconfiglib/examples/Kmenuconfig example uses named choices to be able to
|
||||
# refer to choices by name. Named choices are supported in the C tools too, but
|
||||
# I don't think I've ever seen them used in the wild.
|
||||
#
|
||||
# Sample session:
|
||||
#
|
||||
# $ python Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig
|
||||
#
|
||||
# ======== Example Kconfig configuration ========
|
||||
#
|
||||
# [*] Enable loadable module support (MODULES)
|
||||
# Bool and tristate symbols
|
||||
# [*] Bool symbol (BOOL)
|
||||
# [ ] Dependent bool symbol (BOOL_DEP)
|
||||
# < > Dependent tristate symbol (TRI_DEP)
|
||||
# [ ] First prompt (TWO_MENU_NODES)
|
||||
# < > Tristate symbol (TRI)
|
||||
# [ ] Second prompt (TWO_MENU_NODES)
|
||||
# *** These are selected by TRI_DEP ***
|
||||
# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP)
|
||||
# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP)
|
||||
# String, int, and hex symbols
|
||||
# (foo) String symbol (STRING)
|
||||
# (747) Int symbol (INT)
|
||||
# (0xABC) Hex symbol (HEX)
|
||||
# Various choices
|
||||
# -*- Bool choice (BOOL_CHOICE)
|
||||
# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1)
|
||||
# Bool choice sym 2 (BOOL_CHOICE_SYM_2)
|
||||
# {M} Tristate choice (TRI_CHOICE)
|
||||
# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1)
|
||||
# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2)
|
||||
# [ ] Optional bool choice (OPT_BOOL_CHOICE)
|
||||
#
|
||||
# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL
|
||||
# Value for BOOL (available: n, y): n
|
||||
#
|
||||
# ======== Example Kconfig configuration ========
|
||||
#
|
||||
# [*] Enable loadable module support (MODULES)
|
||||
# Bool and tristate symbols
|
||||
# [ ] Bool symbol (BOOL)
|
||||
# < > Tristate symbol (TRI)
|
||||
# [ ] Second prompt (TWO_MENU_NODES)
|
||||
# *** These are selected by TRI_DEP ***
|
||||
# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP)
|
||||
# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP)
|
||||
# String, int, and hex symbols
|
||||
# (foo) String symbol (STRING)
|
||||
# (747) Int symbol (INT)
|
||||
# (0xABC) Hex symbol (HEX)
|
||||
# Various choices
|
||||
# -*- Bool choice (BOOL_CHOICE)
|
||||
# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1)
|
||||
# Bool choice sym 2 (BOOL_CHOICE_SYM_2)
|
||||
# {M} Tristate choice (TRI_CHOICE)
|
||||
# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1)
|
||||
# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2)
|
||||
# [ ] Optional bool choice (OPT_BOOL_CHOICE)
|
||||
#
|
||||
# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): MODULES
|
||||
# Value for MODULES (available: n, y): n
|
||||
#
|
||||
# ======== Example Kconfig configuration ========
|
||||
#
|
||||
# [ ] Enable loadable module support (MODULES)
|
||||
# Bool and tristate symbols
|
||||
# [ ] Bool symbol (BOOL)
|
||||
# [ ] Tristate symbol (TRI)
|
||||
# [ ] Second prompt (TWO_MENU_NODES)
|
||||
# *** These are selected by TRI_DEP ***
|
||||
# [ ] Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP)
|
||||
# [ ] Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP)
|
||||
# String, int, and hex symbols
|
||||
# (foo) String symbol (STRING)
|
||||
# (747) Int symbol (INT)
|
||||
# (0xABC) Hex symbol (HEX)
|
||||
# Various choices
|
||||
# -*- Bool choice (BOOL_CHOICE)
|
||||
# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1)
|
||||
# Bool choice sym 2 (BOOL_CHOICE_SYM_2)
|
||||
# -*- Tristate choice (TRI_CHOICE)
|
||||
# --> Tristate choice sym 1 (TRI_CHOICE_SYM_1)
|
||||
# Tristate choice sym 2 (TRI_CHOICE_SYM_2)
|
||||
# [ ] Optional bool choice (OPT_BOOL_CHOICE)
|
||||
#
|
||||
# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ^D
|
||||
|
||||
from __future__ import print_function
|
||||
import readline
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, \
|
||||
Symbol, MENU, COMMENT, \
|
||||
BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \
|
||||
expr_value, \
|
||||
TRI_TO_STR
|
||||
|
||||
|
||||
# Python 2/3 compatibility hack
|
||||
if sys.version_info[0] < 3:
|
||||
input = raw_input
|
||||
|
||||
|
||||
def indent_print(s, indent):
|
||||
print(indent*" " + s)
|
||||
|
||||
|
||||
def value_str(sc):
|
||||
"""
|
||||
Returns the value part ("[*]", "<M>", "(foo)" etc.) of a menu entry.
|
||||
|
||||
sc: Symbol or Choice.
|
||||
"""
|
||||
if sc.type in (STRING, INT, HEX):
|
||||
return "({})".format(sc.str_value)
|
||||
|
||||
# BOOL or TRISTATE
|
||||
|
||||
# The choice mode is an upper bound on the visibility of choice symbols, so
|
||||
# we can check the choice symbols' own visibility to see if the choice is
|
||||
# in y mode
|
||||
if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2:
|
||||
# For choices in y mode, print '-->' next to the selected symbol
|
||||
return "-->" if sc.choice.selection is sc else " "
|
||||
|
||||
tri_val_str = (" ", "M", "*")[sc.tri_value]
|
||||
|
||||
if len(sc.assignable) == 1:
|
||||
# Pinned to a single value
|
||||
return "-{}-".format(tri_val_str)
|
||||
|
||||
if sc.type == BOOL:
|
||||
return "[{}]".format(tri_val_str)
|
||||
|
||||
if sc.type == TRISTATE:
|
||||
if sc.assignable == (1, 2):
|
||||
# m and y available
|
||||
return "{" + tri_val_str + "}" # Gets a bit confusing with .format()
|
||||
return "<{}>".format(tri_val_str)
|
||||
|
||||
|
||||
def node_str(node):
|
||||
"""
|
||||
Returns the complete menu entry text for a menu node, or "" for invisible
|
||||
menu nodes. Invisible menu nodes are those that lack a prompt or that do
|
||||
not have a satisfied prompt condition.
|
||||
|
||||
Example return value: "[*] Bool symbol (BOOL)"
|
||||
|
||||
The symbol name is printed in parentheses to the right of the prompt. This
|
||||
is so that symbols can easily be referred to in the configuration
|
||||
interface.
|
||||
"""
|
||||
if not node.prompt:
|
||||
return ""
|
||||
|
||||
# Even for menu nodes for symbols and choices, it's wrong to check
|
||||
# Symbol.visibility / Choice.visibility here. The reason is that a symbol
|
||||
# (and a choice, in theory) can be defined in multiple locations, giving it
|
||||
# multiple menu nodes, which do not necessarily all have the same prompt
|
||||
# visibility. Symbol.visibility / Choice.visibility is calculated as the OR
|
||||
# of the visibility of all the prompts.
|
||||
prompt, prompt_cond = node.prompt
|
||||
if not expr_value(prompt_cond):
|
||||
return ""
|
||||
|
||||
if node.item == MENU:
|
||||
return " " + prompt
|
||||
|
||||
if node.item == COMMENT:
|
||||
return " *** {} ***".format(prompt)
|
||||
|
||||
# Symbol or Choice
|
||||
|
||||
sc = node.item
|
||||
|
||||
if sc.type == UNKNOWN:
|
||||
# Skip symbols defined without a type (these are obscure and generate
|
||||
# a warning)
|
||||
return ""
|
||||
|
||||
# {:3} sets the field width to three. Gives nice alignment for empty string
|
||||
# values.
|
||||
res = "{:3} {}".format(value_str(sc), prompt)
|
||||
|
||||
# Don't print the name for unnamed choices (the normal kind)
|
||||
if sc.name is not None:
|
||||
res += " ({})".format(sc.name)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def print_menuconfig_nodes(node, indent):
|
||||
"""
|
||||
Prints a tree with all the menu entries rooted at 'node'. Child menu
|
||||
entries are indented.
|
||||
"""
|
||||
while node:
|
||||
string = node_str(node)
|
||||
if string:
|
||||
indent_print(string, indent)
|
||||
|
||||
if node.list:
|
||||
print_menuconfig_nodes(node.list, indent + 8)
|
||||
|
||||
node = node.next
|
||||
|
||||
|
||||
def print_menuconfig(kconf):
|
||||
"""
|
||||
Prints all menu entries for the configuration.
|
||||
"""
|
||||
# Print the expanded mainmenu text at the top. This is the same as
|
||||
# kconf.top_node.prompt[0], but with variable references expanded.
|
||||
print("\n======== {} ========\n".format(kconf.mainmenu_text))
|
||||
|
||||
print_menuconfig_nodes(kconf.top_node.list, 0)
|
||||
print("")
|
||||
|
||||
|
||||
def get_value_from_user(sc):
|
||||
"""
|
||||
Prompts the user for a value for the symbol or choice 'sc'. For
|
||||
bool/tristate symbols and choices, provides a list of all the assignable
|
||||
values.
|
||||
"""
|
||||
if not sc.visibility:
|
||||
print(sc.name + " is not currently visible")
|
||||
return False
|
||||
|
||||
prompt = "Value for {}".format(sc.name)
|
||||
if sc.type in (BOOL, TRISTATE):
|
||||
prompt += " (available: {})" \
|
||||
.format(", ".join(TRI_TO_STR[val] for val in sc.assignable))
|
||||
prompt += ": "
|
||||
|
||||
val = input(prompt)
|
||||
|
||||
# Automatically add a "0x" prefix for hex symbols, like the menuconfig
|
||||
# interface does. This isn't done when loading .config files, hence why
|
||||
# set_value() doesn't do it automatically.
|
||||
if sc.type == HEX and not val.startswith(("0x", "0X")):
|
||||
val = "0x" + val
|
||||
|
||||
# Let Kconfiglib itself print a warning here if the value is invalid. We
|
||||
# could also disable warnings temporarily with 'kconf.warn = False' and
|
||||
# print our own warning.
|
||||
return sc.set_value(val)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit("usage: menuconfig.py <Kconfig file>")
|
||||
|
||||
# Load Kconfig configuration files
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
|
||||
# Print the initial configuration tree
|
||||
print_menuconfig(kconf)
|
||||
|
||||
while True:
|
||||
try:
|
||||
cmd = input('Enter a symbol/choice name, "load_config", or '
|
||||
'"write_config" (or press CTRL+D to exit): ').strip()
|
||||
except EOFError:
|
||||
print("")
|
||||
break
|
||||
|
||||
if cmd == "load_config":
|
||||
config_filename = input(".config file to load: ")
|
||||
try:
|
||||
# Returns a message telling which file got loaded
|
||||
print(kconf.load_config(config_filename))
|
||||
except EnvironmentError as e:
|
||||
print(e, file=sys.stderr)
|
||||
|
||||
print_menuconfig(kconf)
|
||||
continue
|
||||
|
||||
if cmd == "write_config":
|
||||
config_filename = input("To this file: ")
|
||||
try:
|
||||
# Returns a message telling which file got saved
|
||||
print(kconf.write_config(config_filename))
|
||||
except EnvironmentError as e:
|
||||
print(e, file=sys.stderr)
|
||||
|
||||
continue
|
||||
|
||||
# Assume 'cmd' is the name of a symbol or choice if it isn't one of the
|
||||
# commands above, prompt the user for a value for it, and print the new
|
||||
# configuration tree
|
||||
|
||||
if cmd in kconf.syms:
|
||||
if get_value_from_user(kconf.syms[cmd]):
|
||||
print_menuconfig(kconf)
|
||||
|
||||
continue
|
||||
|
||||
if cmd in kconf.named_choices:
|
||||
if get_value_from_user(kconf.named_choices[cmd]):
|
||||
print_menuconfig(kconf)
|
||||
|
||||
continue
|
||||
|
||||
print("No symbol/choice named '{}' in the configuration".format(cmd),
|
||||
file=sys.stderr)
|
||||
121
scripts/kconfig/Kconfiglib/examples/merge_config.py
Executable file
121
scripts/kconfig/Kconfiglib/examples/merge_config.py
Executable file
@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This script functions similarly to scripts/kconfig/merge_config.sh from the
|
||||
# kernel tree, merging multiple configurations fragments to produce a complete
|
||||
# .config, with unspecified values filled in as for alldefconfig.
|
||||
#
|
||||
# The generated .config respects symbol dependencies, and a warning is printed
|
||||
# if any symbol gets a different value from the assigned value.
|
||||
#
|
||||
# For a real-world merging example based on this script, see
|
||||
# https://github.com/zephyrproject-rtos/zephyr/blob/master/scripts/kconfig/kconfig.py.
|
||||
#
|
||||
# Here's a demo:
|
||||
#
|
||||
# Kconfig contents:
|
||||
#
|
||||
# config FOO
|
||||
# bool "FOO"
|
||||
#
|
||||
# config BAR
|
||||
# bool "BAR"
|
||||
#
|
||||
# config BAZ
|
||||
# string "BAZ"
|
||||
#
|
||||
# config QAZ
|
||||
# bool "QAZ" if n
|
||||
#
|
||||
#
|
||||
# conf1 contents:
|
||||
#
|
||||
# CONFIG_FOO=y
|
||||
#
|
||||
#
|
||||
# conf2 contents:
|
||||
#
|
||||
# CONFIG_BAR=y
|
||||
#
|
||||
#
|
||||
# conf3 contents:
|
||||
#
|
||||
# # Assigned twice (would generate warning if 'warn_assign_override' was
|
||||
# # True)
|
||||
# # CONFIG_FOO is not set
|
||||
#
|
||||
# # Ops... this symbol doesn't exist
|
||||
# CONFIG_OPS=y
|
||||
#
|
||||
# CONFIG_BAZ="baz string"
|
||||
#
|
||||
#
|
||||
# conf4 contents:
|
||||
#
|
||||
# CONFIG_QAZ=y
|
||||
#
|
||||
#
|
||||
# Running:
|
||||
#
|
||||
# $ python(3) merge_config.py Kconfig merged conf1 conf2 conf3 conf4
|
||||
# Merged configuration 'conf1'
|
||||
# Merged configuration 'conf2'
|
||||
# conf3:5: warning: attempt to assign the value 'y' to the undefined symbol OPS
|
||||
# Merged configuration 'conf3'
|
||||
# Merged configuration 'conf4'
|
||||
# Configuration saved to 'merged'
|
||||
# warning: QAZ (defined at Kconfig:10) was assigned the value 'y' but got the value 'n' -- check dependencies
|
||||
# $ cat merged
|
||||
# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)
|
||||
# # CONFIG_FOO is not set
|
||||
# CONFIG_BAR=y
|
||||
# CONFIG_BAZ="baz string"
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, BOOL, TRISTATE, TRI_TO_STR
|
||||
|
||||
|
||||
if len(sys.argv) < 4:
|
||||
sys.exit("usage: merge_config.py Kconfig merged_config config1 [config2 ...]")
|
||||
|
||||
kconf = Kconfig(sys.argv[1], suppress_traceback=True)
|
||||
|
||||
# Enable warnings for assignments to undefined symbols
|
||||
kconf.warn_assign_undef = True
|
||||
|
||||
# (This script uses alldefconfig as the base. Other starting states could be
|
||||
# set up here as well. The approach in examples/allnoconfig_simpler.py could
|
||||
# provide an allnoconfig starting state for example.)
|
||||
|
||||
# Disable warnings generated for multiple assignments to the same symbol within
|
||||
# a (set of) configuration files. Assigning a symbol multiple times might be
|
||||
# done intentionally when merging configuration files.
|
||||
kconf.warn_assign_override = False
|
||||
kconf.warn_assign_redun = False
|
||||
|
||||
# Create a merged configuration by loading the fragments with replace=False.
|
||||
# load_config() and write_config() returns a message to print.
|
||||
for config in sys.argv[3:]:
|
||||
print(kconf.load_config(config, replace=False))
|
||||
|
||||
# Write the merged configuration
|
||||
print(kconf.write_config(sys.argv[2]))
|
||||
|
||||
# Print warnings for symbols whose actual value doesn't match the assigned
|
||||
# value
|
||||
for sym in kconf.defined_syms:
|
||||
# Was the symbol assigned to?
|
||||
if sym.user_value is not None:
|
||||
# Tristate values are represented as 0, 1, 2. Having them as
|
||||
# "n", "m", "y" is more convenient here, so convert.
|
||||
if sym.type in (BOOL, TRISTATE):
|
||||
user_value = TRI_TO_STR[sym.user_value]
|
||||
else:
|
||||
user_value = sym.user_value
|
||||
|
||||
if user_value != sym.str_value:
|
||||
print("warning: {} was assigned the value '{}' but got the "
|
||||
"value '{}' -- check dependencies".format(
|
||||
sym.name_and_loc, user_value, sym.str_value),
|
||||
file=sys.stderr)
|
||||
199
scripts/kconfig/Kconfiglib/examples/print_config_tree.py
Normal file
199
scripts/kconfig/Kconfiglib/examples/print_config_tree.py
Normal file
@ -0,0 +1,199 @@
|
||||
# Prints menu entries as a tree with its value in the .config file. This can be
|
||||
# handy e.g. for diffing between different .config files or versions of Kconfig files.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=print_config_tree.py [SCRIPT_ARG=<.config>]
|
||||
#
|
||||
# If the variable WITH_HELP_DESC is modified to 'True', the help is added
|
||||
# to the symbols.
|
||||
#
|
||||
# Here's a notation guide. The notation matches the one used by menuconfig
|
||||
# (scripts/kconfig/mconf):
|
||||
#
|
||||
# [ ] prompt - Bool
|
||||
# < > prompt - Tristate
|
||||
# {M} prompt - Tristate selected to m. Can only be set to m or y.
|
||||
# -*- prompt - Bool/tristate selected to y, pinning it
|
||||
# -M- prompt - Tristate selected to m that also has m visibility,
|
||||
# pinning it to m
|
||||
# (foo) prompt - String/int/hex symbol with value "foo"
|
||||
# --> prompt - The selected symbol in a choice in y mode. This
|
||||
# syntax is unique to this example.
|
||||
#
|
||||
# When modules are disabled, the .type attribute of TRISTATE symbols and
|
||||
# choices automatically changes to BOOL. This trick is used by the C
|
||||
# implementation as well, and gives the expected behavior without having to do
|
||||
# anything extra here. The original type is available in .orig_type if needed.
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# $ make scriptconfig SCRIPT=Kconfiglib/examples/print_config_tree.py [SCRIPT_ARG=<.config file>]
|
||||
#
|
||||
# ======== Linux/x86 4.9.82 Kernel Configuration ========
|
||||
#
|
||||
# [*] 64-bit kernel (64BIT)
|
||||
# General setup
|
||||
# () Cross-compiler tool prefix (CROSS_COMPILE)
|
||||
# [ ] Compile also drivers which will not load (COMPILE_TEST)
|
||||
# () Local version - append to kernel release (LOCALVERSION)
|
||||
# [*] Automatically append version information to the version string (LOCALVERSION_AUTO)
|
||||
# -*- Kernel compression mode
|
||||
# ...
|
||||
#
|
||||
# With the variable WITH_HELP_DESC modified to 'True':
|
||||
#
|
||||
# ======== Linux/x86 4.9.82 Kernel Configuration ========
|
||||
#
|
||||
# [*] 64-bit kernel - Say yes to build a 64-bit kernel - formerly known as x86_64 Say no to build a 32-bit kernel - formerly known as i386 (64BIT)
|
||||
# General setup
|
||||
# () Cross-compiler tool prefix - Same as running 'make CROSS_COMPILE=prefix-' but stored for default make runs in this kernel build directory. You don't need to set this unless you want the configured kernel build directory to select the cross-compiler automatically. (CROSS_COMPILE)
|
||||
# [ ] Compile also drivers which will not load - Some drivers can be compiled on a different platform than they are intended to be run on. Despite they cannot be loaded there (or even when they load they cannot be used due to missing HW support), developers still, opposing to distributors, might want to build such drivers to compile-test them. If you are a developer and want to build everything available, say Y here. If you are a user/distributor, say N here to exclude useless drivers to be distributed. (COMPILE_TEST)
|
||||
# ...
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, \
|
||||
Symbol, MENU, COMMENT, \
|
||||
BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \
|
||||
expr_value
|
||||
|
||||
|
||||
# Add help description to output
|
||||
WITH_HELP_DESC = False
|
||||
|
||||
|
||||
def indent_print(s, indent):
|
||||
print(indent*" " + s)
|
||||
|
||||
|
||||
def value_str(sc):
|
||||
"""
|
||||
Returns the value part ("[*]", "<M>", "(foo)" etc.) of a menu entry.
|
||||
|
||||
sc: Symbol or Choice.
|
||||
"""
|
||||
if sc.type in (STRING, INT, HEX):
|
||||
return "({})".format(sc.str_value)
|
||||
|
||||
# BOOL or TRISTATE
|
||||
|
||||
# The choice mode is an upper bound on the visibility of choice symbols, so
|
||||
# we can check the choice symbols' own visibility to see if the choice is
|
||||
# in y mode
|
||||
if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2:
|
||||
# For choices in y mode, print '-->' next to the selected symbol
|
||||
return "-->" if sc.choice.selection is sc else " "
|
||||
|
||||
tri_val_str = (" ", "M", "*")[sc.tri_value]
|
||||
|
||||
if len(sc.assignable) == 1:
|
||||
# Pinned to a single value
|
||||
return "-{}-".format(tri_val_str)
|
||||
|
||||
if sc.type == BOOL:
|
||||
return "[{}]".format(tri_val_str)
|
||||
|
||||
if sc.type == TRISTATE:
|
||||
if sc.assignable == (1, 2):
|
||||
# m and y available
|
||||
return "{" + tri_val_str + "}" # Gets a bit confusing with .format()
|
||||
return "<{}>".format(tri_val_str)
|
||||
|
||||
|
||||
def node_str(node):
|
||||
"""
|
||||
Returns the complete menu entry text for a menu node, or "" for invisible
|
||||
menu nodes. Invisible menu nodes are those that lack a prompt or that do
|
||||
not have a satisfied prompt condition.
|
||||
|
||||
Example return value: "[*] Bool symbol (BOOL)"
|
||||
|
||||
The symbol name is printed in parentheses to the right of the prompt.
|
||||
"""
|
||||
if not node.prompt:
|
||||
return ""
|
||||
|
||||
# Even for menu nodes for symbols and choices, it's wrong to check
|
||||
# Symbol.visibility / Choice.visibility here. The reason is that a symbol
|
||||
# (and a choice, in theory) can be defined in multiple locations, giving it
|
||||
# multiple menu nodes, which do not necessarily all have the same prompt
|
||||
# visibility. Symbol.visibility / Choice.visibility is calculated as the OR
|
||||
# of the visibility of all the prompts.
|
||||
prompt, prompt_cond = node.prompt
|
||||
if not expr_value(prompt_cond):
|
||||
return ""
|
||||
|
||||
if node.item == MENU:
|
||||
return " " + prompt
|
||||
|
||||
if node.item == COMMENT:
|
||||
return " *** {} ***".format(prompt)
|
||||
|
||||
# Symbol or Choice
|
||||
|
||||
sc = node.item
|
||||
|
||||
if sc.type == UNKNOWN:
|
||||
# Skip symbols defined without a type (these are obscure and generate
|
||||
# a warning)
|
||||
return ""
|
||||
|
||||
# Add help text
|
||||
if WITH_HELP_DESC:
|
||||
prompt += ' - ' + str(node.help).replace('\n', ' ').replace('\r', '')
|
||||
|
||||
# {:3} sets the field width to three. Gives nice alignment for empty string
|
||||
# values.
|
||||
res = "{:3} {}".format(value_str(sc), prompt)
|
||||
|
||||
# Don't print the name for unnamed choices (the normal kind)
|
||||
if sc.name is not None:
|
||||
res += " ({})".format(sc.name)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def print_menuconfig_nodes(node, indent):
|
||||
"""
|
||||
Prints a tree with all the menu entries rooted at 'node'. Child menu
|
||||
entries are indented.
|
||||
"""
|
||||
while node:
|
||||
string = node_str(node)
|
||||
if string:
|
||||
indent_print(string, indent)
|
||||
|
||||
if node.list:
|
||||
print_menuconfig_nodes(node.list, indent + 8)
|
||||
|
||||
node = node.next
|
||||
|
||||
|
||||
def print_menuconfig(kconf):
|
||||
"""
|
||||
Prints all menu entries for the configuration.
|
||||
"""
|
||||
# Print the expanded mainmenu text at the top. This is the same as
|
||||
# kconf.top_node.prompt[0], but with variable references expanded.
|
||||
print("\n======== {} ========\n".format(kconf.mainmenu_text))
|
||||
|
||||
print_menuconfig_nodes(kconf.top_node.list, 0)
|
||||
print("")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Load Kconfig configuration files
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
|
||||
# Set default .config file or load it from argv
|
||||
if len(sys.argv) == 2:
|
||||
config_filename = '.config'
|
||||
else:
|
||||
config_filename = sys.argv[2]
|
||||
|
||||
kconf.load_config(config_filename)
|
||||
|
||||
# Print the configuration tree
|
||||
print_menuconfig(kconf)
|
||||
54
scripts/kconfig/Kconfiglib/examples/print_sym_info.py
Normal file
54
scripts/kconfig/Kconfiglib/examples/print_sym_info.py
Normal file
@ -0,0 +1,54 @@
|
||||
# Loads a Kconfig and a .config and prints a symbol.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/print_sym_info.py SCRIPT_ARG=<name>
|
||||
#
|
||||
# Example output for SCRIPT_ARG=MODULES:
|
||||
#
|
||||
# menuconfig MODULES
|
||||
# bool
|
||||
# prompt "Enable loadable module support"
|
||||
# option modules
|
||||
# help
|
||||
# Kernel modules are small pieces of compiled code which can
|
||||
# be inserted in the running kernel, rather than being
|
||||
# permanently built into the kernel. You use the "modprobe"
|
||||
# tool to add (and sometimes remove) them. If you say Y here,
|
||||
# many parts of the kernel can be built as modules (by
|
||||
# answering M instead of Y where indicated): this is most
|
||||
# useful for infrequently used options which are not required
|
||||
# for booting. For more information, see the man pages for
|
||||
# modprobe, lsmod, modinfo, insmod and rmmod.
|
||||
#
|
||||
# If you say Y here, you will need to run "make
|
||||
# modules_install" to put the modules under /lib/modules/
|
||||
# where modprobe can find them (you may need to be root to do
|
||||
# this).
|
||||
#
|
||||
# If unsure, say Y.
|
||||
#
|
||||
# value = n
|
||||
# visibility = y
|
||||
# currently assignable values: n, y
|
||||
# defined at init/Kconfig:1674
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, TRI_TO_STR
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=<name>')
|
||||
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
sym = kconf.syms[sys.argv[2]]
|
||||
|
||||
print(sym)
|
||||
print("value = " + sym.str_value)
|
||||
print("visibility = " + TRI_TO_STR[sym.visibility])
|
||||
print("currently assignable values: " +
|
||||
", ".join([TRI_TO_STR[v] for v in sym.assignable]))
|
||||
|
||||
for node in sym.nodes:
|
||||
print("defined at {}:{}".format(node.filename, node.linenr))
|
||||
75
scripts/kconfig/Kconfiglib/examples/print_tree.py
Normal file
75
scripts/kconfig/Kconfiglib/examples/print_tree.py
Normal file
@ -0,0 +1,75 @@
|
||||
# Prints the menu tree of the configuration. Dependencies between symbols can
|
||||
# sometimes implicitly alter the menu structure (see kconfig-language.txt), and
|
||||
# that's implemented too.
|
||||
#
|
||||
# Note: See the Kconfig.node_iter() function as well, which provides a simpler
|
||||
# interface for walking the menu tree.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# ...
|
||||
# config HAVE_KERNEL_LZO
|
||||
# config HAVE_KERNEL_LZ4
|
||||
# choice
|
||||
# config KERNEL_GZIP
|
||||
# config KERNEL_BZIP2
|
||||
# config KERNEL_LZMA
|
||||
# config KERNEL_XZ
|
||||
# config KERNEL_LZO
|
||||
# config KERNEL_LZ4
|
||||
# config DEFAULT_HOSTNAME
|
||||
# config SWAP
|
||||
# config SYSVIPC
|
||||
# config SYSVIPC_SYSCTL
|
||||
# config POSIX_MQUEUE
|
||||
# config POSIX_MQUEUE_SYSCTL
|
||||
# config CROSS_MEMORY_ATTACH
|
||||
# config FHANDLE
|
||||
# config USELIB
|
||||
# config AUDIT
|
||||
# config HAVE_ARCH_AUDITSYSCALL
|
||||
# config AUDITSYSCALL
|
||||
# config AUDIT_WATCH
|
||||
# config AUDIT_TREE
|
||||
# menu "IRQ subsystem"
|
||||
# config MAY_HAVE_SPARSE_IRQ
|
||||
# config GENERIC_IRQ_LEGACY
|
||||
# config GENERIC_IRQ_PROBE
|
||||
# ...
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, Symbol, Choice, MENU, COMMENT
|
||||
|
||||
|
||||
def indent_print(s, indent):
|
||||
print(indent*" " + s)
|
||||
|
||||
|
||||
def print_items(node, indent):
|
||||
while node:
|
||||
if isinstance(node.item, Symbol):
|
||||
indent_print("config " + node.item.name, indent)
|
||||
|
||||
elif isinstance(node.item, Choice):
|
||||
indent_print("choice", indent)
|
||||
|
||||
elif node.item == MENU:
|
||||
indent_print('menu "{}"'.format(node.prompt[0]), indent)
|
||||
|
||||
elif node.item == COMMENT:
|
||||
indent_print('comment "{}"'.format(node.prompt[0]), indent)
|
||||
|
||||
|
||||
if node.list:
|
||||
print_items(node.list, indent + 2)
|
||||
|
||||
node = node.next
|
||||
|
||||
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
print_items(kconf.top_node, 0)
|
||||
154
scripts/kconfig/Kconfiglib/genconfig.py
Executable file
154
scripts/kconfig/Kconfiglib/genconfig.py
Executable file
@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Generates a header file with #defines from the configuration, matching the
|
||||
format of include/generated/autoconf.h in the Linux kernel.
|
||||
|
||||
Optionally, also writes the configuration output as a .config file. See
|
||||
--config-out.
|
||||
|
||||
The --sync-deps, --file-list, and --env-list options generate information that
|
||||
can be used to avoid needless rebuilds/reconfigurations.
|
||||
|
||||
Before writing a header or configuration file, Kconfiglib compares the old
|
||||
contents of the file against the new contents. If there's no change, the write
|
||||
is skipped. This avoids updating file metadata like the modification time, and
|
||||
might save work depending on your build setup.
|
||||
|
||||
By default, the configuration is generated from '.config'. A different
|
||||
configuration file can be passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
A custom header string can be inserted at the beginning of generated
|
||||
configuration and header files by setting the KCONFIG_CONFIG_HEADER and
|
||||
KCONFIG_AUTOHEADER_HEADER environment variables, respectively (this also works
|
||||
for other scripts). The string is not automatically made a comment (this is by
|
||||
design, to allow anything to be added), and no trailing newline is added, so
|
||||
add '/* */', '#', and newlines as appropriate.
|
||||
|
||||
See https://www.gnu.org/software/make/manual/make.html#Multi_002dLine for a
|
||||
handy way to define multi-line variables in makefiles, for use with custom
|
||||
headers. Remember to export the variable to the environment.
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
DEFAULT_SYNC_DEPS_PATH = "deps/"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--header-path",
|
||||
metavar="HEADER_FILE",
|
||||
help="""
|
||||
Path to write the generated header file to. If not specified, the path in the
|
||||
environment variable KCONFIG_AUTOHEADER is used if it is set, and 'config.h'
|
||||
otherwise.
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"--config-out",
|
||||
metavar="CONFIG_FILE",
|
||||
help="""
|
||||
Write the configuration to CONFIG_FILE. This is useful if you include .config
|
||||
files in Makefiles, as the generated configuration file will be a full .config
|
||||
file even if .config is outdated. The generated configuration matches what
|
||||
olddefconfig would produce. If you use sync-deps, you can include
|
||||
deps/auto.conf instead. --config-out is meant for cases where incremental build
|
||||
information isn't needed.
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"--sync-deps",
|
||||
metavar="OUTPUT_DIR",
|
||||
nargs="?",
|
||||
const=DEFAULT_SYNC_DEPS_PATH,
|
||||
help="""
|
||||
Enable generation of symbol dependency information for incremental builds,
|
||||
optionally specifying the output directory (default: {}). See the docstring of
|
||||
Kconfig.sync_deps() in Kconfiglib for more information.
|
||||
""".format(DEFAULT_SYNC_DEPS_PATH))
|
||||
|
||||
parser.add_argument(
|
||||
"--file-list",
|
||||
metavar="OUTPUT_FILE",
|
||||
help="""
|
||||
Write a list of all Kconfig files to OUTPUT_FILE, with one file per line. The
|
||||
paths are relative to $srctree (or to the current directory if $srctree is
|
||||
unset). Files appear in the order they're 'source'd.
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"--env-list",
|
||||
metavar="OUTPUT_FILE",
|
||||
help="""
|
||||
Write a list of all environment variables referenced in Kconfig files to
|
||||
OUTPUT_FILE, with one variable per line. Each line has the format NAME=VALUE.
|
||||
Only environment variables referenced with the preprocessor $(VAR) syntax are
|
||||
included, and not variables referenced with the older $VAR syntax (which is
|
||||
only supported for backwards compatibility).
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"kconfig",
|
||||
metavar="KCONFIG",
|
||||
nargs="?",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
kconf.load_config()
|
||||
|
||||
if args.header_path is None:
|
||||
if "KCONFIG_AUTOHEADER" in os.environ:
|
||||
kconf.write_autoconf()
|
||||
else:
|
||||
# Kconfiglib defaults to include/generated/autoconf.h to be
|
||||
# compatible with the C tools. 'config.h' is used here instead for
|
||||
# backwards compatibility. It's probably a saner default for tools
|
||||
# as well.
|
||||
kconf.write_autoconf("config.h")
|
||||
else:
|
||||
kconf.write_autoconf(args.header_path)
|
||||
|
||||
if args.config_out is not None:
|
||||
kconf.write_config(args.config_out, save_old=False)
|
||||
|
||||
if args.sync_deps is not None:
|
||||
kconf.sync_deps(args.sync_deps)
|
||||
|
||||
if args.file_list is not None:
|
||||
with _open_write(args.file_list) as f:
|
||||
for path in kconf.kconfig_filenames:
|
||||
f.write(path + "\n")
|
||||
|
||||
if args.env_list is not None:
|
||||
with _open_write(args.env_list) as f:
|
||||
for env_var in kconf.env_vars:
|
||||
f.write("{}={}\n".format(env_var, os.environ[env_var]))
|
||||
|
||||
|
||||
def _open_write(path):
|
||||
# Python 2/3 compatibility. io.open() is available on both, but makes
|
||||
# write() expect 'unicode' strings on Python 2.
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
return open(path, "w")
|
||||
return open(path, "w", encoding="utf-8")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
2324
scripts/kconfig/Kconfiglib/guiconfig.py
Executable file
2324
scripts/kconfig/Kconfiglib/guiconfig.py
Executable file
File diff suppressed because it is too large
Load Diff
7160
scripts/kconfig/Kconfiglib/kconfiglib.py
Normal file
7160
scripts/kconfig/Kconfiglib/kconfiglib.py
Normal file
File diff suppressed because it is too large
Load Diff
76
scripts/kconfig/Kconfiglib/listnewconfig.py
Executable file
76
scripts/kconfig/Kconfiglib/listnewconfig.py
Executable file
@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Lists all user-modifiable symbols that are not given a value in the
|
||||
configuration file. Usually, these are new symbols that have been added to the
|
||||
Kconfig files.
|
||||
|
||||
The default configuration filename is '.config'. A different filename can be
|
||||
passed in the KCONFIG_CONFIG environment variable.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, BOOL, TRISTATE, INT, HEX, STRING, TRI_TO_STR
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--show-help", "-l",
|
||||
action="store_true",
|
||||
help="Show any help texts as well")
|
||||
|
||||
parser.add_argument(
|
||||
"kconfig",
|
||||
metavar="KCONFIG",
|
||||
nargs="?",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = Kconfig(args.kconfig, suppress_traceback=True)
|
||||
# Make it possible to filter this message out
|
||||
print(kconf.load_config(), file=sys.stderr)
|
||||
|
||||
for sym in kconf.unique_defined_syms:
|
||||
# Only show symbols that can be toggled. Choice symbols are a special
|
||||
# case in that sym.assignable will be (2,) (length 1) for visible
|
||||
# symbols in choices in y mode, but they can still be toggled by
|
||||
# selecting some other symbol.
|
||||
if sym.user_value is None and \
|
||||
(len(sym.assignable) > 1 or
|
||||
(sym.visibility and (sym.orig_type in (INT, HEX, STRING) or
|
||||
sym.choice))):
|
||||
|
||||
# Don't reuse the 'config_string' format for bool/tristate symbols,
|
||||
# to show n-valued symbols as 'CONFIG_FOO=n' instead of
|
||||
# '# CONFIG_FOO is not set'. This matches the C tools.
|
||||
if sym.orig_type in (BOOL, TRISTATE):
|
||||
s = "{}{}={}\n".format(kconf.config_prefix, sym.name,
|
||||
TRI_TO_STR[sym.tri_value])
|
||||
else:
|
||||
s = sym.config_string
|
||||
|
||||
print(s, end="")
|
||||
if args.show_help:
|
||||
for node in sym.nodes:
|
||||
if node.help is not None:
|
||||
# Indent by two spaces. textwrap.indent() is not
|
||||
# available in Python 2 (it's 3.3+).
|
||||
print("\n".join(" " + line
|
||||
for line in node.help.split("\n")))
|
||||
break
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
48
scripts/kconfig/Kconfiglib/makefile.patch
Normal file
48
scripts/kconfig/Kconfiglib/makefile.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 93daf46f309b0c8f86149ef58c4906387d054c22 Mon Sep 17 00:00:00 2001
|
||||
From: Ulf Magnusson <ulfalizer@gmail.com>
|
||||
Date: Tue, 9 Jun 2015 13:01:34 +0200
|
||||
Subject: [PATCH] Kconfiglib scripts/kconfig/Makefile patch
|
||||
|
||||
---
|
||||
scripts/kconfig/Makefile | 29 +++++++++++++++++++++++++++++
|
||||
1 file changed, 29 insertions(+)
|
||||
|
||||
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
|
||||
index 3f327e21f60e..8b7dd1292005 100644
|
||||
--- a/scripts/kconfig/Makefile
|
||||
+++ b/scripts/kconfig/Makefile
|
||||
@@ -27,2 +27,31 @@ gconfig: $(obj)/gconf
|
||||
|
||||
+PHONY += scriptconfig iscriptconfig kmenuconfig guiconfig dumpvarsconfig
|
||||
+
|
||||
+PYTHONCMD ?= python
|
||||
+kpython := PYTHONPATH=$(srctree)/Kconfiglib:$$PYTHONPATH $(PYTHONCMD)
|
||||
+
|
||||
+ifneq ($(filter scriptconfig,$(MAKECMDGOALS)),)
|
||||
+ifndef SCRIPT
|
||||
+$(error Use "make scriptconfig SCRIPT=<path to script> [SCRIPT_ARG=<argument>]")
|
||||
+endif
|
||||
+endif
|
||||
+
|
||||
+scriptconfig:
|
||||
+ $(Q)$(kpython) $(SCRIPT) $(Kconfig) $(if $(SCRIPT_ARG),"$(SCRIPT_ARG)")
|
||||
+
|
||||
+iscriptconfig:
|
||||
+ $(Q)$(kpython) -i -c \
|
||||
+ "import kconfiglib; \
|
||||
+ kconf = kconfiglib.Kconfig('$(Kconfig)'); \
|
||||
+ print('A Kconfig instance \'kconf\' for the architecture $(ARCH) has been created.')"
|
||||
+
|
||||
+kmenuconfig:
|
||||
+ $(Q)$(kpython) $(srctree)/Kconfiglib/menuconfig.py $(Kconfig)
|
||||
+
|
||||
+guiconfig:
|
||||
+ $(Q)$(kpython) $(srctree)/Kconfiglib/guiconfig.py $(Kconfig)
|
||||
+
|
||||
+dumpvarsconfig:
|
||||
+ $(Q)$(kpython) $(srctree)/Kconfiglib/examples/dumpvars.py $(Kconfig)
|
||||
+
|
||||
menuconfig: $(obj)/mconf
|
||||
--
|
||||
2.20.1
|
||||
|
||||
3278
scripts/kconfig/Kconfiglib/menuconfig.py
Executable file
3278
scripts/kconfig/Kconfiglib/menuconfig.py
Executable file
File diff suppressed because it is too large
Load Diff
246
scripts/kconfig/Kconfiglib/oldconfig.py
Executable file
246
scripts/kconfig/Kconfiglib/oldconfig.py
Executable file
@ -0,0 +1,246 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Implements oldconfig functionality.
|
||||
|
||||
1. Loads existing .config
|
||||
2. Prompts for the value of all modifiable symbols/choices that
|
||||
aren't already set in the .config
|
||||
3. Writes an updated .config
|
||||
|
||||
The default input/output filename is '.config'. A different filename can be
|
||||
passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
When overwriting a configuration file, the old version is saved to
|
||||
<filename>.old (e.g. .config.old).
|
||||
|
||||
Entering '?' displays the help text of the symbol/choice, if any.
|
||||
|
||||
Unlike 'make oldconfig', this script doesn't print menu titles and comments,
|
||||
but gives Kconfig definition locations. Printing menus and comments would be
|
||||
pretty easy to add: Look at the parents of each item, and print all menu
|
||||
prompts and comments unless they have already been printed (assuming you want
|
||||
to skip "irrelevant" menus).
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Symbol, Choice, BOOL, TRISTATE, HEX, standard_kconfig
|
||||
|
||||
|
||||
# Python 2/3 compatibility hack
|
||||
if sys.version_info[0] < 3:
|
||||
input = raw_input
|
||||
|
||||
|
||||
def _main():
|
||||
# Earlier symbols in Kconfig files might depend on later symbols and become
|
||||
# visible if their values change. This flag is set to True if the value of
|
||||
# any symbol changes, in which case we rerun the oldconfig to check for new
|
||||
# visible symbols.
|
||||
global conf_changed
|
||||
|
||||
kconf = standard_kconfig(__doc__)
|
||||
print(kconf.load_config())
|
||||
|
||||
while True:
|
||||
conf_changed = False
|
||||
|
||||
for node in kconf.node_iter():
|
||||
oldconfig(node)
|
||||
|
||||
if not conf_changed:
|
||||
break
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
def oldconfig(node):
|
||||
"""
|
||||
Prompts the user for a value if node.item is a visible symbol/choice with
|
||||
no user value.
|
||||
"""
|
||||
# See main()
|
||||
global conf_changed
|
||||
|
||||
# Only symbols and choices can be configured
|
||||
if not isinstance(node.item, (Symbol, Choice)):
|
||||
return
|
||||
|
||||
# Skip symbols and choices that aren't visible
|
||||
if not node.item.visibility:
|
||||
return
|
||||
|
||||
# Skip symbols and choices that don't have a prompt (at this location)
|
||||
if not node.prompt:
|
||||
return
|
||||
|
||||
if isinstance(node.item, Symbol):
|
||||
sym = node.item
|
||||
|
||||
# Skip symbols that already have a user value
|
||||
if sym.user_value is not None:
|
||||
return
|
||||
|
||||
# Skip symbols that can only have a single value, due to selects
|
||||
if len(sym.assignable) == 1:
|
||||
return
|
||||
|
||||
# Skip symbols in choices in y mode. We ask once for the entire choice
|
||||
# instead.
|
||||
if sym.choice and sym.choice.tri_value == 2:
|
||||
return
|
||||
|
||||
# Loop until the user enters a valid value or enters a blank string
|
||||
# (for the default value)
|
||||
while True:
|
||||
val = input("{} ({}) [{}] ".format(
|
||||
node.prompt[0], _name_and_loc_str(sym),
|
||||
_default_value_str(sym)))
|
||||
|
||||
if val == "?":
|
||||
_print_help(node)
|
||||
continue
|
||||
|
||||
# Substitute a blank string with the default value the symbol
|
||||
# would get
|
||||
if not val:
|
||||
val = sym.str_value
|
||||
|
||||
# Automatically add a "0x" prefix for hex symbols, like the
|
||||
# menuconfig interface does. This isn't done when loading .config
|
||||
# files, hence why set_value() doesn't do it automatically.
|
||||
if sym.type == HEX and not val.startswith(("0x", "0X")):
|
||||
val = "0x" + val
|
||||
|
||||
old_str_val = sym.str_value
|
||||
|
||||
# Kconfiglib itself will print a warning here if the value
|
||||
# is invalid, so we don't need to bother
|
||||
if sym.set_value(val):
|
||||
# Valid value input. We're done with this node.
|
||||
|
||||
if sym.str_value != old_str_val:
|
||||
conf_changed = True
|
||||
|
||||
return
|
||||
|
||||
else:
|
||||
choice = node.item
|
||||
|
||||
# Skip choices that already have a visible user selection...
|
||||
if choice.user_selection and choice.user_selection.visibility == 2:
|
||||
# ...unless there are new visible symbols in the choice. (We know
|
||||
# they have y (2) visibility in that case, because m-visible
|
||||
# symbols get demoted to n-visibility in y-mode choices, and the
|
||||
# user-selected symbol had visibility y.)
|
||||
for sym in choice.syms:
|
||||
if sym is not choice.user_selection and sym.visibility and \
|
||||
sym.user_value is None:
|
||||
# New visible symbols in the choice
|
||||
break
|
||||
else:
|
||||
# No new visible symbols in the choice
|
||||
return
|
||||
|
||||
# Get a list of available selections. The mode of the choice limits
|
||||
# the visibility of the choice value symbols, so this will indirectly
|
||||
# skip choices in n and m mode.
|
||||
options = [sym for sym in choice.syms if sym.visibility == 2]
|
||||
|
||||
if not options:
|
||||
# No y-visible choice value symbols
|
||||
return
|
||||
|
||||
# Loop until the user enters a valid selection or a blank string (for
|
||||
# the default selection)
|
||||
while True:
|
||||
print("{} ({})".format(node.prompt[0], _name_and_loc_str(choice)))
|
||||
|
||||
for i, sym in enumerate(options, 1):
|
||||
print("{} {}. {} ({})".format(
|
||||
">" if sym is choice.selection else " ",
|
||||
i,
|
||||
# Assume people don't define choice symbols with multiple
|
||||
# prompts. That generates a warning anyway.
|
||||
sym.nodes[0].prompt[0],
|
||||
sym.name))
|
||||
|
||||
sel_index = input("choice[1-{}]: ".format(len(options)))
|
||||
|
||||
if sel_index == "?":
|
||||
_print_help(node)
|
||||
continue
|
||||
|
||||
# Pick the default selection if the string is blank
|
||||
if not sel_index:
|
||||
choice.selection.set_value(2)
|
||||
break
|
||||
|
||||
try:
|
||||
sel_index = int(sel_index)
|
||||
except ValueError:
|
||||
print("Bad index", file=sys.stderr)
|
||||
continue
|
||||
|
||||
if not 1 <= sel_index <= len(options):
|
||||
print("Bad index", file=sys.stderr)
|
||||
continue
|
||||
|
||||
# Valid selection
|
||||
|
||||
if options[sel_index - 1].tri_value != 2:
|
||||
conf_changed = True
|
||||
|
||||
options[sel_index - 1].set_value(2)
|
||||
break
|
||||
|
||||
# Give all of the non-selected visible choice symbols the user value n.
|
||||
# This makes it so that the choice is no longer considered new once we
|
||||
# do additional passes, if the reason that it was considered new was
|
||||
# that it had new visible choice symbols.
|
||||
#
|
||||
# Only giving visible choice symbols the user value n means we will
|
||||
# prompt for the choice again if later user selections make more new
|
||||
# choice symbols visible, which is correct.
|
||||
for sym in choice.syms:
|
||||
if sym is not choice.user_selection and sym.visibility:
|
||||
sym.set_value(0)
|
||||
|
||||
|
||||
def _name_and_loc_str(sc):
|
||||
# Helper for printing the name of the symbol/choice 'sc' along with the
|
||||
# location(s) in the Kconfig files where it is defined. Unnamed choices
|
||||
# return "choice" instead of the name.
|
||||
|
||||
return "{}, defined at {}".format(
|
||||
sc.name or "choice",
|
||||
", ".join("{}:{}".format(node.filename, node.linenr)
|
||||
for node in sc.nodes))
|
||||
|
||||
|
||||
def _print_help(node):
|
||||
print("\n" + (node.help or "No help text\n"))
|
||||
|
||||
|
||||
def _default_value_str(sym):
|
||||
# Returns the "m/M/y" string in e.g.
|
||||
#
|
||||
# TRISTATE_SYM prompt (TRISTATE_SYM, defined at Kconfig:9) [n/M/y]:
|
||||
#
|
||||
# For string/int/hex, returns the default value as-is.
|
||||
|
||||
if sym.type in (BOOL, TRISTATE):
|
||||
return "/".join(("NMY" if sym.tri_value == tri else "nmy")[tri]
|
||||
for tri in sym.assignable)
|
||||
|
||||
# string/int/hex
|
||||
return sym.str_value
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
||||
28
scripts/kconfig/Kconfiglib/olddefconfig.py
Executable file
28
scripts/kconfig/Kconfiglib/olddefconfig.py
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Updates an old .config file or creates a new one, by filling in default values
|
||||
for all new symbols. This is the same as picking the default selection for all
|
||||
symbols in oldconfig, or entering the menuconfig interface and immediately
|
||||
saving.
|
||||
|
||||
The default input/output filename is '.config'. A different filename can be
|
||||
passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
When overwriting a configuration file, the old version is saved to
|
||||
<filename>.old (e.g. .config.old).
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
print(kconf.load_config())
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
49
scripts/kconfig/Kconfiglib/savedefconfig.py
Executable file
49
scripts/kconfig/Kconfiglib/savedefconfig.py
Executable file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Saves a minimal configuration file that only lists symbols that differ in value
|
||||
from their defaults. Loading such a configuration file is equivalent to loading
|
||||
the "full" configuration file.
|
||||
|
||||
Minimal configuration files are handy to start from when editing configuration
|
||||
files by hand.
|
||||
|
||||
The default input configuration file is '.config'. A different input filename
|
||||
can be passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Note: Minimal configurations can also be generated from within the menuconfig
|
||||
interface.
|
||||
"""
|
||||
import argparse
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--kconfig",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
parser.add_argument(
|
||||
"--out",
|
||||
metavar="MINIMAL_CONFIGURATION",
|
||||
default="defconfig",
|
||||
help="Output filename for minimal configuration (default: defconfig)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
print(kconf.load_config())
|
||||
print(kconf.write_min_config(args.out))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
scripts/kconfig/Kconfiglib/setconfig.py
Executable file
92
scripts/kconfig/Kconfiglib/setconfig.py
Executable file
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Simple utility for setting configuration values from the command line.
|
||||
|
||||
Sample usage:
|
||||
|
||||
$ setconfig FOO_SUPPORT=y BAR_BITS=8
|
||||
|
||||
Note: Symbol names should not be prefixed with 'CONFIG_'.
|
||||
|
||||
The exit status on errors is 1.
|
||||
|
||||
The default input/output configuration file is '.config'. A different filename
|
||||
can be passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
When overwriting a configuration file, the old version is saved to
|
||||
<filename>.old (e.g. .config.old).
|
||||
"""
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--kconfig",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
parser.add_argument(
|
||||
"--no-check-exists",
|
||||
dest="check_exists",
|
||||
action="store_false",
|
||||
help="Ignore assignments to non-existent symbols instead of erroring "
|
||||
"out")
|
||||
|
||||
parser.add_argument(
|
||||
"--no-check-value",
|
||||
dest="check_value",
|
||||
action="store_false",
|
||||
help="Ignore assignments that didn't \"take\" (where the symbol got a "
|
||||
"different value, e.g. due to unsatisfied dependencies) instead "
|
||||
"of erroring out")
|
||||
|
||||
parser.add_argument(
|
||||
"assignments",
|
||||
metavar="ASSIGNMENT",
|
||||
nargs="*",
|
||||
help="A 'NAME=value' assignment")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
print(kconf.load_config())
|
||||
|
||||
for arg in args.assignments:
|
||||
if "=" not in arg:
|
||||
sys.exit("error: no '=' in assignment: '{}'".format(arg))
|
||||
name, value = arg.split("=", 1)
|
||||
|
||||
if name not in kconf.syms:
|
||||
if not args.check_exists:
|
||||
continue
|
||||
sys.exit("error: no symbol '{}' in configuration".format(name))
|
||||
|
||||
sym = kconf.syms[name]
|
||||
|
||||
if not sym.set_value(value):
|
||||
sys.exit("error: '{}' is an invalid value for the {} symbol {}"
|
||||
.format(value, kconfiglib.TYPE_TO_STR[sym.orig_type],
|
||||
name))
|
||||
|
||||
if args.check_value and sym.str_value != value:
|
||||
sys.exit("error: {} was assigned the value '{}', but got the "
|
||||
"value '{}'. Check the symbol's dependencies, and make "
|
||||
"sure that it has a prompt."
|
||||
.format(name, value, sym.str_value))
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
7
scripts/kconfig/Kconfiglib/setup.cfg
Normal file
7
scripts/kconfig/Kconfiglib/setup.cfg
Normal file
@ -0,0 +1,7 @@
|
||||
[bdist_wheel]
|
||||
# We support both Python 2 and Python 3
|
||||
universal = 1
|
||||
|
||||
[metadata]
|
||||
# Include the license file in wheels
|
||||
license_file = LICENSE.txt
|
||||
96
scripts/kconfig/Kconfiglib/setup.py
Normal file
96
scripts/kconfig/Kconfiglib/setup.py
Normal file
@ -0,0 +1,96 @@
|
||||
import io
|
||||
import os
|
||||
|
||||
import setuptools
|
||||
|
||||
|
||||
setuptools.setup(
|
||||
name="kconfiglib",
|
||||
# MAJOR.MINOR.PATCH, per http://semver.org
|
||||
version="14.1.0",
|
||||
description="A flexible Python Kconfig implementation",
|
||||
|
||||
# Make sure that README.rst decodes on Python 3 in environments that use
|
||||
# the C locale (which implies ASCII), by explicitly giving the encoding.
|
||||
#
|
||||
# io.open() has the 'encoding' parameter on both Python 2 and 3. open()
|
||||
# doesn't have it on Python 2. This lets us use the same code for both.
|
||||
long_description=io.open(
|
||||
os.path.join(os.path.dirname(__file__), "README.rst"),
|
||||
encoding="utf-8"
|
||||
).read(),
|
||||
|
||||
url="https://github.com/ulfalizer/Kconfiglib",
|
||||
author='Ulf "Ulfalizer" Magnusson',
|
||||
author_email="ulfalizer@gmail.com",
|
||||
keywords="kconfig, kbuild, menuconfig, configuration-management",
|
||||
license="ISC",
|
||||
|
||||
py_modules=(
|
||||
"kconfiglib",
|
||||
"menuconfig",
|
||||
"guiconfig",
|
||||
"genconfig",
|
||||
"oldconfig",
|
||||
"olddefconfig",
|
||||
"savedefconfig",
|
||||
"defconfig",
|
||||
"alldefconfig",
|
||||
"allnoconfig",
|
||||
"allmodconfig",
|
||||
"allyesconfig",
|
||||
"listnewconfig",
|
||||
"setconfig",
|
||||
),
|
||||
|
||||
entry_points={
|
||||
"console_scripts": (
|
||||
"menuconfig = menuconfig:_main",
|
||||
"guiconfig = guiconfig:_main",
|
||||
"genconfig = genconfig:main",
|
||||
"oldconfig = oldconfig:_main",
|
||||
"olddefconfig = olddefconfig:main",
|
||||
"savedefconfig = savedefconfig:main",
|
||||
"defconfig = defconfig:main",
|
||||
"alldefconfig = alldefconfig:main",
|
||||
"allnoconfig = allnoconfig:main",
|
||||
"allmodconfig = allmodconfig:main",
|
||||
"allyesconfig = allyesconfig:main",
|
||||
"listnewconfig = listnewconfig:main",
|
||||
"setconfig = setconfig:main",
|
||||
)
|
||||
},
|
||||
|
||||
# Note: windows-curses is not automatically installed on Windows anymore,
|
||||
# because it made Kconfiglib impossible to install on MSYS2 with pip
|
||||
|
||||
# Needs support for unnumbered {} in format() and argparse
|
||||
python_requires=">=2.7,!=3.0.*,!=3.1.*",
|
||||
|
||||
project_urls={
|
||||
"GitHub repository": "https://github.com/ulfalizer/Kconfiglib",
|
||||
"Examples": "https://github.com/ulfalizer/Kconfiglib/tree/master/examples",
|
||||
},
|
||||
|
||||
classifiers=[
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Build Tools",
|
||||
"Topic :: System :: Operating System Kernels :: Linux",
|
||||
"License :: OSI Approved :: ISC License (ISCL)",
|
||||
"Operating System :: POSIX",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.2",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
]
|
||||
)
|
||||
12
scripts/kconfig/Kconfiglib/tests/Kappend
Normal file
12
scripts/kconfig/Kconfiglib/tests/Kappend
Normal file
@ -0,0 +1,12 @@
|
||||
config MODULES
|
||||
def_bool y
|
||||
|
||||
config BOOL
|
||||
bool "bool 1"
|
||||
|
||||
config STRING
|
||||
string "string"
|
||||
|
||||
config IGNOREME
|
||||
bool "ignore me"
|
||||
default y
|
||||
230
scripts/kconfig/Kconfiglib/tests/Kassignable
Normal file
230
scripts/kconfig/Kconfiglib/tests/Kassignable
Normal file
@ -0,0 +1,230 @@
|
||||
config MODULES
|
||||
bool "modules"
|
||||
option modules
|
||||
|
||||
|
||||
# Things that should never be .assignable
|
||||
|
||||
if UNDEFINED && "const"
|
||||
endif
|
||||
|
||||
config NO_PROMPT
|
||||
bool
|
||||
|
||||
config STRING
|
||||
string "string"
|
||||
|
||||
config INT
|
||||
int "int"
|
||||
|
||||
config HEX
|
||||
hex "hex"
|
||||
|
||||
|
||||
# Non-selected symbols
|
||||
|
||||
config Y_VIS_BOOL
|
||||
bool "y-vis bool"
|
||||
|
||||
config M_VIS_BOOL
|
||||
bool "m-vis bool" if m
|
||||
|
||||
config N_VIS_BOOL
|
||||
bool "n-vis bool" if n
|
||||
|
||||
config Y_VIS_TRI
|
||||
tristate "y-vis tri"
|
||||
|
||||
config M_VIS_TRI
|
||||
tristate "m-vis tri" if m
|
||||
|
||||
config N_VIS_TRI
|
||||
tristate "n-vis tri" if n
|
||||
|
||||
|
||||
# Symbols selected to y
|
||||
|
||||
config Y_SELECTOR
|
||||
def_tristate y
|
||||
|
||||
select Y_SEL_Y_VIS_BOOL
|
||||
select Y_SEL_M_VIS_BOOL
|
||||
select Y_SEL_N_VIS_BOOL
|
||||
|
||||
select Y_SEL_Y_VIS_TRI
|
||||
select Y_SEL_M_VIS_TRI
|
||||
select Y_SEL_N_VIS_TRI
|
||||
|
||||
config Y_SEL_Y_VIS_BOOL
|
||||
bool "y-sel y-vis bool"
|
||||
|
||||
config Y_SEL_M_VIS_BOOL
|
||||
bool "y-sel m-vis bool" if m
|
||||
|
||||
config Y_SEL_N_VIS_BOOL
|
||||
bool "y-sel n-vis bool" if n
|
||||
|
||||
config Y_SEL_Y_VIS_TRI
|
||||
tristate "y-sel y-vis tri"
|
||||
|
||||
config Y_SEL_M_VIS_TRI
|
||||
tristate "y-sel m-vis tri" if m
|
||||
|
||||
config Y_SEL_N_VIS_TRI
|
||||
tristate "y-sel n-vis tri" if n
|
||||
|
||||
|
||||
# Symbols selected to m
|
||||
|
||||
config M_SELECTOR
|
||||
def_tristate m
|
||||
|
||||
select M_SEL_Y_VIS_BOOL
|
||||
select M_SEL_M_VIS_BOOL
|
||||
select M_SEL_N_VIS_BOOL
|
||||
|
||||
select M_SEL_Y_VIS_TRI
|
||||
select M_SEL_M_VIS_TRI
|
||||
select M_SEL_N_VIS_TRI
|
||||
|
||||
config M_SEL_Y_VIS_BOOL
|
||||
bool "m-sel y-vis bool"
|
||||
|
||||
config M_SEL_M_VIS_BOOL
|
||||
bool "m-sel m-vis bool" if m
|
||||
|
||||
config M_SEL_N_VIS_BOOL
|
||||
bool "m-sel n-vis bool" if n
|
||||
|
||||
config M_SEL_Y_VIS_TRI
|
||||
tristate "m-sel y-vis tri"
|
||||
|
||||
config M_SEL_M_VIS_TRI
|
||||
tristate "m-sel m-vis tri" if m
|
||||
|
||||
config M_SEL_N_VIS_TRI
|
||||
tristate "m-sel n-vis tri" if n
|
||||
|
||||
|
||||
# Symbols implied to y
|
||||
|
||||
config Y_IMPLIER
|
||||
def_tristate y
|
||||
|
||||
imply Y_IMP_Y_VIS_BOOL
|
||||
imply Y_IMP_M_VIS_BOOL
|
||||
imply Y_IMP_N_VIS_BOOL
|
||||
|
||||
imply Y_IMP_Y_VIS_TRI
|
||||
imply Y_IMP_M_VIS_TRI
|
||||
imply Y_IMP_N_VIS_TRI
|
||||
|
||||
config Y_IMP_Y_VIS_BOOL
|
||||
bool "y-imp y-vis bool"
|
||||
|
||||
config Y_IMP_M_VIS_BOOL
|
||||
bool "y-imp m-vis bool" if m
|
||||
|
||||
config Y_IMP_N_VIS_BOOL
|
||||
bool "y-imp n-vis bool" if n
|
||||
|
||||
config Y_IMP_Y_VIS_TRI
|
||||
tristate "y-imp y-vis tri"
|
||||
|
||||
config Y_IMP_M_VIS_TRI
|
||||
tristate "y-imp m-vis tri" if m
|
||||
|
||||
config Y_IMP_N_VIS_TRI
|
||||
tristate "y-imp n-vis tri" if n
|
||||
|
||||
|
||||
# Symbols implied to m (never affects assignable values)
|
||||
|
||||
config M_IMPLIER
|
||||
def_tristate m
|
||||
|
||||
imply M_IMP_Y_VIS_BOOL
|
||||
imply M_IMP_M_VIS_BOOL
|
||||
imply M_IMP_N_VIS_BOOL
|
||||
|
||||
imply M_IMP_Y_VIS_TRI
|
||||
imply M_IMP_M_VIS_TRI
|
||||
imply M_IMP_N_VIS_TRI
|
||||
|
||||
config M_IMP_Y_VIS_BOOL
|
||||
bool "m-imp y-vis bool"
|
||||
|
||||
config M_IMP_M_VIS_BOOL
|
||||
bool "m-imp m-vis bool" if m
|
||||
|
||||
config M_IMP_N_VIS_BOOL
|
||||
bool "m-imp n-vis bool" if n
|
||||
|
||||
config M_IMP_Y_VIS_TRI
|
||||
tristate "m-imp y-vis tri"
|
||||
|
||||
config M_IMP_M_VIS_TRI
|
||||
tristate "m-imp m-vis tri" if m
|
||||
|
||||
config M_IMP_N_VIS_TRI
|
||||
tristate "m-imp n-vis tri" if n
|
||||
|
||||
|
||||
# Symbols in y-mode choice
|
||||
|
||||
choice Y_CHOICE
|
||||
bool "y-mode choice"
|
||||
|
||||
config Y_CHOICE_BOOL
|
||||
bool "y-mode choice bool"
|
||||
|
||||
config Y_CHOICE_TRISTATE
|
||||
tristate "y-mode choice tristate"
|
||||
|
||||
config Y_CHOICE_N_VIS_TRISTATE
|
||||
tristate "y-mode choice tristate invisible" if n
|
||||
|
||||
endchoice
|
||||
|
||||
|
||||
# Symbols in m/y-mode choice
|
||||
|
||||
choice MY_CHOICE
|
||||
tristate "m/y-mode choice"
|
||||
|
||||
config MY_CHOICE_BOOL
|
||||
bool "m/y-mode choice bool"
|
||||
|
||||
config MY_CHOICE_TRISTATE
|
||||
tristate "m/y-mode choice tristate"
|
||||
|
||||
config MY_CHOICE_N_VIS_TRISTATE
|
||||
tristate "m/y-mode choice tristate invisible" if n
|
||||
|
||||
endchoice
|
||||
|
||||
|
||||
# Choices with some other possible modes
|
||||
|
||||
choice NMY_CHOICE
|
||||
tristate "n/m/y-mode choice"
|
||||
optional
|
||||
endchoice
|
||||
|
||||
choice NY_CHOICE
|
||||
bool "n/y-mode choice"
|
||||
optional
|
||||
endchoice
|
||||
|
||||
choice NM_CHOICE
|
||||
tristate "n/m-mode choice" if m
|
||||
optional
|
||||
endchoice
|
||||
|
||||
choice M_CHOICE
|
||||
tristate "m-mode choice" if m
|
||||
endchoice
|
||||
|
||||
choice N_CHOICE
|
||||
tristate "n-mode choice" if n
|
||||
endchoice
|
||||
198
scripts/kconfig/Kconfiglib/tests/Kchoice
Normal file
198
scripts/kconfig/Kconfiglib/tests/Kchoice
Normal file
@ -0,0 +1,198 @@
|
||||
config MODULES
|
||||
bool "modules"
|
||||
|
||||
# bool/tristate and optional
|
||||
|
||||
choice BOOL
|
||||
bool "bool"
|
||||
config B_1
|
||||
tristate "B_1"
|
||||
config B_2
|
||||
tristate "B_2"
|
||||
endchoice
|
||||
|
||||
choice BOOL_OPT
|
||||
bool "bool optional"
|
||||
optional
|
||||
config BO_1
|
||||
tristate "BO_1"
|
||||
config BO_2
|
||||
tristate "BO_2"
|
||||
endchoice
|
||||
|
||||
choice TRISTATE
|
||||
tristate "tristate"
|
||||
config T_1
|
||||
tristate "T_1"
|
||||
config T_2
|
||||
tristate "T_2"
|
||||
endchoice
|
||||
|
||||
choice TRISTATE_OPT
|
||||
tristate "tristate optional"
|
||||
optional
|
||||
config TO_1
|
||||
tristate "TO_1"
|
||||
config TO_2
|
||||
tristate "TO_2"
|
||||
endchoice
|
||||
|
||||
# m-visibility
|
||||
|
||||
choice BOOL_M
|
||||
bool "bool m" if m
|
||||
config BM_1
|
||||
tristate "BM_1"
|
||||
config BM_2
|
||||
tristate "BM_2"
|
||||
endchoice
|
||||
|
||||
choice TRISTATE_M
|
||||
tristate "tristate m" if m
|
||||
config TM_1
|
||||
tristate "TM_1"
|
||||
config TM_2
|
||||
tristate "TM_2"
|
||||
endchoice
|
||||
|
||||
# Defaults
|
||||
|
||||
config TRISTATE_SYM
|
||||
tristate "tristate"
|
||||
|
||||
choice DEFAULTS
|
||||
bool "defaults"
|
||||
default OPT_1 if n
|
||||
default OPT_2 if TRISTATE_SYM
|
||||
default OPT_4
|
||||
config OPT_1
|
||||
tristate "OPT_1"
|
||||
config OPT_2
|
||||
tristate "OPT_2"
|
||||
config OPT_3
|
||||
tristate "OPT_3"
|
||||
config OPT_4
|
||||
tristate "OPT_4"
|
||||
endchoice
|
||||
|
||||
choice DEFAULTS_NOT_VISIBLE
|
||||
bool "defaults not visible"
|
||||
# Skipped due to condition
|
||||
default OPT_6 if n
|
||||
# Skipped because OPT_7 is not visible
|
||||
default OPT_7
|
||||
# This one should apply
|
||||
default OPT_8
|
||||
config OPT_5
|
||||
tristate "OPT_5"
|
||||
config OPT_6
|
||||
tristate "OPT_6"
|
||||
config OPT_7
|
||||
tristate "OPT_7" if n
|
||||
config OPT_8
|
||||
tristate "OPT_8"
|
||||
config OPT_9
|
||||
tristate "OPT_9"
|
||||
endchoice
|
||||
|
||||
# Choices without an explicitly specified type should get the type of the first
|
||||
# symbol with a type
|
||||
|
||||
choice NO_TYPE_BOOL
|
||||
prompt "no type bool"
|
||||
config NTB_1
|
||||
bool "NTB_1"
|
||||
config NTB_2
|
||||
tristate "NTB_2"
|
||||
endchoice
|
||||
|
||||
choice NO_TYPE_TRISTATE
|
||||
prompt "no type tristate"
|
||||
config NTT_1
|
||||
config NTT_2
|
||||
tristate "NTB_2"
|
||||
config NTT_3
|
||||
bool "NTT_3"
|
||||
endchoice
|
||||
|
||||
# Choice items without an explicitly specified type should get the type of the
|
||||
# choice
|
||||
|
||||
choice MISSING_MEMBER_TYPES_1
|
||||
bool "missing member types"
|
||||
config MMT_1
|
||||
config MMT_2
|
||||
config MMT_3
|
||||
tristate
|
||||
endchoice
|
||||
|
||||
choice MISSING_MEMBER_TYPES_2
|
||||
config MMT_4
|
||||
config MMT_5
|
||||
bool
|
||||
endchoice
|
||||
|
||||
# Choice where the default selection (the first symbol) depends on another
|
||||
# symbol. If that symbol becomes 'n', the default selection should change to
|
||||
# the first visible symbol in the choice.
|
||||
|
||||
choice DEFAULT_WITH_DEP
|
||||
bool "default with dep"
|
||||
|
||||
config A
|
||||
bool "A"
|
||||
depends on DEP
|
||||
|
||||
config B
|
||||
bool "B"
|
||||
|
||||
endchoice
|
||||
|
||||
config DEP
|
||||
bool "dep"
|
||||
|
||||
# Choice with symbols that shouldn't be considered choice symbols because they
|
||||
# depend on the preceding symbol. This might be a kconfig bug, but some things
|
||||
# use it, so we need to emulate it.
|
||||
|
||||
choice WEIRD_SYMS
|
||||
bool "weird symbols that aren't considered part of the choice"
|
||||
|
||||
# Only WS1 is part of the choice
|
||||
config WS1
|
||||
bool "WS1"
|
||||
|
||||
config WS2
|
||||
bool "WS2"
|
||||
depends on WS1
|
||||
|
||||
config WS3
|
||||
bool
|
||||
depends on WS2
|
||||
|
||||
config WS4
|
||||
bool
|
||||
depends on WS1
|
||||
|
||||
config WS5
|
||||
bool "WS5" if WS1
|
||||
|
||||
# 'if' has the same effect, so only WS6 is part of the choice
|
||||
config WS6
|
||||
bool "WS6"
|
||||
|
||||
if WS6
|
||||
|
||||
config WS7
|
||||
bool
|
||||
|
||||
config WS8
|
||||
bool "WS8"
|
||||
|
||||
endif
|
||||
|
||||
# Should also be part of the choice
|
||||
config WS9
|
||||
bool "WS9"
|
||||
|
||||
endchoice
|
||||
8
scripts/kconfig/Kconfiglib/tests/Kdefconfig_existent
Normal file
8
scripts/kconfig/Kconfiglib/tests/Kdefconfig_existent
Normal file
@ -0,0 +1,8 @@
|
||||
# $FOO is "defconfig_2"
|
||||
|
||||
config A
|
||||
string
|
||||
option defconfig_list
|
||||
default "Kconfiglib/tests/defconfig_1" if y && !n && n
|
||||
default "Kconfiglib/tests/$FOO"
|
||||
default "Kconfiglib/tests/defconfig_1"
|
||||
10
scripts/kconfig/Kconfiglib/tests/Kdefconfig_existent_but_n
Normal file
10
scripts/kconfig/Kconfiglib/tests/Kdefconfig_existent_but_n
Normal file
@ -0,0 +1,10 @@
|
||||
# $FOO is "defconfig_2"
|
||||
# Should produce None due to the "depends on n"
|
||||
|
||||
config A
|
||||
string
|
||||
depends on n
|
||||
option defconfig_list
|
||||
default "Kconfiglib/tests/defconfig_1" if y && !n && n
|
||||
default "Kconfiglib/tests/$FOO"
|
||||
default "Kconfiglib/tests/defconfig_1"
|
||||
5
scripts/kconfig/Kconfiglib/tests/Kdefconfig_nonexistent
Normal file
5
scripts/kconfig/Kconfiglib/tests/Kdefconfig_nonexistent
Normal file
@ -0,0 +1,5 @@
|
||||
config A
|
||||
string
|
||||
option defconfig_list
|
||||
default "Kconfiglib/tests/non_existent_1"
|
||||
default "Kconfiglib/tests/non_existent_2"
|
||||
5
scripts/kconfig/Kconfiglib/tests/Kdefconfig_srctree
Normal file
5
scripts/kconfig/Kconfiglib/tests/Kdefconfig_srctree
Normal file
@ -0,0 +1,5 @@
|
||||
config A
|
||||
string
|
||||
option defconfig_list
|
||||
default "sub/defconfig_in_sub" # Assume this doesn't exist
|
||||
default "Kconfiglib/tests/defconfig_2"
|
||||
173
scripts/kconfig/Kconfiglib/tests/Kdepcopy
Normal file
173
scripts/kconfig/Kconfiglib/tests/Kdepcopy
Normal file
@ -0,0 +1,173 @@
|
||||
# We verify that the properties below end up in definition order
|
||||
|
||||
config MULTIDEF
|
||||
bool
|
||||
default A
|
||||
default B
|
||||
select AA
|
||||
imply AA
|
||||
|
||||
if FOO
|
||||
|
||||
config MULTIDEF
|
||||
default C
|
||||
default D
|
||||
select BB
|
||||
imply BB
|
||||
|
||||
if BAR
|
||||
|
||||
config MULTIDEF
|
||||
default E
|
||||
default F
|
||||
select CC
|
||||
imply CC
|
||||
|
||||
menu "menu"
|
||||
|
||||
config MULTIDEF
|
||||
default G
|
||||
default H
|
||||
select DD
|
||||
imply DD
|
||||
|
||||
config MULTIDEF
|
||||
default I
|
||||
default J
|
||||
select EE
|
||||
imply EE
|
||||
|
||||
endmenu
|
||||
|
||||
config MULTIDEF
|
||||
default K
|
||||
default L
|
||||
select FF
|
||||
imply FF
|
||||
|
||||
config MULTIDEF
|
||||
default M
|
||||
default N
|
||||
select GG
|
||||
imply GG
|
||||
|
||||
endif
|
||||
|
||||
config MULTIDEF
|
||||
default O
|
||||
default P
|
||||
select HH
|
||||
select II
|
||||
imply HH
|
||||
imply II
|
||||
|
||||
endif
|
||||
|
||||
config MULTIDEF
|
||||
default Q
|
||||
default R
|
||||
select JJ
|
||||
imply JJ
|
||||
|
||||
|
||||
# Same test with choice symbols involved
|
||||
|
||||
config MULTIDEF_CHOICE
|
||||
bool
|
||||
select A
|
||||
|
||||
choice
|
||||
bool "choice"
|
||||
|
||||
config MULTIDEF_CHOICE
|
||||
bool "multidef choice"
|
||||
select B
|
||||
|
||||
endchoice
|
||||
|
||||
config MULTIDEF_CHOICE
|
||||
bool
|
||||
select C
|
||||
|
||||
|
||||
# Same test with ranges involved
|
||||
|
||||
config MULTIDEF_RANGE
|
||||
int
|
||||
range A _
|
||||
|
||||
menu "menu"
|
||||
|
||||
config MULTIDEF_RANGE
|
||||
int
|
||||
range B _
|
||||
|
||||
if FOO
|
||||
|
||||
config MULTIDEF_RANGE
|
||||
int
|
||||
range C _
|
||||
|
||||
endif
|
||||
|
||||
config MULTIDEF_RANGE
|
||||
int
|
||||
range D _
|
||||
|
||||
endmenu
|
||||
|
||||
config MULTIDEF_RANGE
|
||||
int
|
||||
range E _
|
||||
|
||||
config MULTIDEF_RANGE
|
||||
int
|
||||
range F _
|
||||
|
||||
|
||||
# Same test for a choice
|
||||
|
||||
choice MULTICHOICE
|
||||
bool "choice"
|
||||
default A
|
||||
|
||||
config A
|
||||
bool "A"
|
||||
|
||||
config B
|
||||
bool "B"
|
||||
|
||||
config C
|
||||
bool "C"
|
||||
|
||||
config D
|
||||
bool "C"
|
||||
|
||||
config E
|
||||
bool "C"
|
||||
|
||||
endchoice
|
||||
|
||||
if FOO
|
||||
|
||||
choice MULTICHOICE
|
||||
default B
|
||||
endchoice
|
||||
|
||||
menu "menu"
|
||||
|
||||
choice MULTICHOICE
|
||||
default C
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
choice MULTICHOICE
|
||||
default D
|
||||
endchoice
|
||||
|
||||
endif
|
||||
|
||||
choice MULTICHOICE
|
||||
default E
|
||||
endchoice
|
||||
3
scripts/kconfig/Kconfiglib/tests/Kdeploop0
Normal file
3
scripts/kconfig/Kconfiglib/tests/Kdeploop0
Normal file
@ -0,0 +1,3 @@
|
||||
config FOO
|
||||
bool
|
||||
depends on FOO
|
||||
3
scripts/kconfig/Kconfiglib/tests/Kdeploop1
Normal file
3
scripts/kconfig/Kconfiglib/tests/Kdeploop1
Normal file
@ -0,0 +1,3 @@
|
||||
config FOO
|
||||
bool
|
||||
select FOO
|
||||
48
scripts/kconfig/Kconfiglib/tests/Kdeploop10
Normal file
48
scripts/kconfig/Kconfiglib/tests/Kdeploop10
Normal file
@ -0,0 +1,48 @@
|
||||
config A
|
||||
bool
|
||||
depends on B
|
||||
|
||||
config B
|
||||
bool
|
||||
depends on C = 7
|
||||
|
||||
config C
|
||||
int
|
||||
range D 8
|
||||
|
||||
config D
|
||||
int
|
||||
default 3 if E
|
||||
default 8
|
||||
|
||||
config E
|
||||
bool
|
||||
|
||||
config F
|
||||
bool
|
||||
select E if G
|
||||
|
||||
config G
|
||||
bool
|
||||
depends on H
|
||||
|
||||
choice
|
||||
bool "choice"
|
||||
|
||||
config H
|
||||
bool "H"
|
||||
depends on I
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
bool "choice" if J
|
||||
|
||||
config I
|
||||
bool "I"
|
||||
|
||||
endchoice
|
||||
|
||||
config J
|
||||
bool
|
||||
depends on A
|
||||
3
scripts/kconfig/Kconfiglib/tests/Kdeploop2
Normal file
3
scripts/kconfig/Kconfiglib/tests/Kdeploop2
Normal file
@ -0,0 +1,3 @@
|
||||
config FOO
|
||||
bool
|
||||
default FOO
|
||||
3
scripts/kconfig/Kconfiglib/tests/Kdeploop3
Normal file
3
scripts/kconfig/Kconfiglib/tests/Kdeploop3
Normal file
@ -0,0 +1,3 @@
|
||||
config FOO
|
||||
bool
|
||||
default y if FOO
|
||||
7
scripts/kconfig/Kconfiglib/tests/Kdeploop4
Normal file
7
scripts/kconfig/Kconfiglib/tests/Kdeploop4
Normal file
@ -0,0 +1,7 @@
|
||||
config FOO
|
||||
bool
|
||||
depends on BAR
|
||||
|
||||
config BAR
|
||||
bool
|
||||
depends on FOO
|
||||
7
scripts/kconfig/Kconfiglib/tests/Kdeploop5
Normal file
7
scripts/kconfig/Kconfiglib/tests/Kdeploop5
Normal file
@ -0,0 +1,7 @@
|
||||
config FOO
|
||||
bool
|
||||
select BAR
|
||||
|
||||
config BAR
|
||||
bool
|
||||
select FOO
|
||||
6
scripts/kconfig/Kconfiglib/tests/Kdeploop6
Normal file
6
scripts/kconfig/Kconfiglib/tests/Kdeploop6
Normal file
@ -0,0 +1,6 @@
|
||||
config FOO
|
||||
bool
|
||||
|
||||
config BAR
|
||||
bool
|
||||
select FOO if FOO
|
||||
11
scripts/kconfig/Kconfiglib/tests/Kdeploop7
Normal file
11
scripts/kconfig/Kconfiglib/tests/Kdeploop7
Normal file
@ -0,0 +1,11 @@
|
||||
choice
|
||||
bool "choice"
|
||||
|
||||
config FOO
|
||||
bool "foo"
|
||||
depends on BAR
|
||||
|
||||
config BAR
|
||||
bool "bar"
|
||||
|
||||
endchoice
|
||||
8
scripts/kconfig/Kconfiglib/tests/Kdeploop8
Normal file
8
scripts/kconfig/Kconfiglib/tests/Kdeploop8
Normal file
@ -0,0 +1,8 @@
|
||||
choice
|
||||
bool "choice"
|
||||
default FOO if FOO
|
||||
|
||||
config FOO
|
||||
bool "foo"
|
||||
|
||||
endchoice
|
||||
7
scripts/kconfig/Kconfiglib/tests/Kdeploop9
Normal file
7
scripts/kconfig/Kconfiglib/tests/Kdeploop9
Normal file
@ -0,0 +1,7 @@
|
||||
choice
|
||||
bool "choice" if FOO
|
||||
|
||||
config FOO
|
||||
bool "foo"
|
||||
|
||||
endchoice
|
||||
30
scripts/kconfig/Kconfiglib/tests/Kdirdep
Normal file
30
scripts/kconfig/Kconfiglib/tests/Kdirdep
Normal file
@ -0,0 +1,30 @@
|
||||
config NO_DEP_SYM
|
||||
bool
|
||||
|
||||
config DEP_SYM
|
||||
bool
|
||||
depends on A
|
||||
|
||||
config DEP_SYM
|
||||
depends on B && C
|
||||
|
||||
config DEP_SYM
|
||||
depends on !D
|
||||
|
||||
|
||||
choice NO_DEP_CHOICE
|
||||
bool "no dep. choice"
|
||||
endchoice
|
||||
|
||||
choice DEP_CHOICE
|
||||
bool "dep. choice"
|
||||
depends on A
|
||||
endchoice
|
||||
|
||||
choice DEP_CHOICE
|
||||
depends on B
|
||||
endchoice
|
||||
|
||||
choice DEP_CHOICE
|
||||
depends on C
|
||||
endchoice
|
||||
3
scripts/kconfig/Kconfiglib/tests/Kescape
Normal file
3
scripts/kconfig/Kconfiglib/tests/Kescape
Normal file
@ -0,0 +1,3 @@
|
||||
config STRING
|
||||
string "string"
|
||||
default "\"\\"
|
||||
34
scripts/kconfig/Kconfiglib/tests/Keval
Normal file
34
scripts/kconfig/Kconfiglib/tests/Keval
Normal file
@ -0,0 +1,34 @@
|
||||
# Enabled/disabled in the test
|
||||
config MODULES
|
||||
bool "modules"
|
||||
option modules
|
||||
|
||||
config N
|
||||
def_tristate n
|
||||
|
||||
config M
|
||||
def_tristate m
|
||||
|
||||
menuconfig Y
|
||||
def_tristate y
|
||||
prompt "foo"
|
||||
|
||||
config Y_STRING
|
||||
string
|
||||
default "y"
|
||||
|
||||
config FOO_BAR_STRING
|
||||
string
|
||||
default "foo bar"
|
||||
|
||||
config INT_37
|
||||
int
|
||||
default 37
|
||||
|
||||
config HEX_0X37
|
||||
hex
|
||||
default 0x37
|
||||
|
||||
config HEX_37
|
||||
hex
|
||||
default 37
|
||||
11
scripts/kconfig/Kconfiglib/tests/Kexpr_items
Normal file
11
scripts/kconfig/Kconfiglib/tests/Kexpr_items
Normal file
@ -0,0 +1,11 @@
|
||||
config TEST
|
||||
bool
|
||||
default A && (B || !C && D = "E") || F > G || !!!H
|
||||
|
||||
choice CHOICE
|
||||
bool "choice"
|
||||
|
||||
config TEST_CHOICE
|
||||
bool "test choice" if A
|
||||
|
||||
endchoice
|
||||
5
scripts/kconfig/Kconfiglib/tests/Kheader
Normal file
5
scripts/kconfig/Kconfiglib/tests/Kheader
Normal file
@ -0,0 +1,5 @@
|
||||
# Used to test headers in .config and header files
|
||||
|
||||
config FOO
|
||||
bool "foo"
|
||||
default y
|
||||
50
scripts/kconfig/Kconfiglib/tests/Khelp
Normal file
50
scripts/kconfig/Kconfiglib/tests/Khelp
Normal file
@ -0,0 +1,50 @@
|
||||
config TWO_HELP_STRINGS
|
||||
bool
|
||||
help
|
||||
first help string
|
||||
|
||||
|
||||
|
||||
|
||||
config TWO_HELP_STRINGS
|
||||
help
|
||||
second help string
|
||||
|
||||
config NO_BLANK_AFTER_HELP
|
||||
bool
|
||||
help
|
||||
help for
|
||||
NO_BLANK_AFTER_HELP
|
||||
choice CHOICE_HELP
|
||||
bool "choice with help"
|
||||
help
|
||||
help for
|
||||
CHOICE_HELP
|
||||
endchoice
|
||||
|
||||
config HELP_TERMINATED_BY_COMMENT
|
||||
bool
|
||||
help
|
||||
a
|
||||
b
|
||||
c
|
||||
#
|
||||
|
||||
config TRICKY_HELP
|
||||
bool
|
||||
-help---
|
||||
|
||||
|
||||
a
|
||||
b
|
||||
c
|
||||
|
||||
d
|
||||
e
|
||||
f
|
||||
|
||||
|
||||
g
|
||||
h
|
||||
i
|
||||
#
|
||||
99
scripts/kconfig/Kconfiglib/tests/Kifremoval
Normal file
99
scripts/kconfig/Kconfiglib/tests/Kifremoval
Normal file
@ -0,0 +1,99 @@
|
||||
# Test some tricky cases that give consecutive 'if' nodes even after
|
||||
# flattening. Simple cases are exercised a ton elsewhere.
|
||||
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
|
||||
config A
|
||||
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
|
||||
config B
|
||||
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
|
||||
config C
|
||||
|
||||
if X
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
endif
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
endif
|
||||
config D
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
|
||||
menu "E"
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
endif
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
endif
|
||||
endmenu
|
||||
|
||||
menu "F"
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
menu "G"
|
||||
endmenu
|
||||
endif
|
||||
endmenu
|
||||
|
||||
choice H
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
endif
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
endif
|
||||
endchoice
|
||||
|
||||
choice I
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
config J
|
||||
endif
|
||||
endchoice
|
||||
|
||||
if X
|
||||
endif
|
||||
if X
|
||||
endif
|
||||
145
scripts/kconfig/Kconfiglib/tests/Kimply
Normal file
145
scripts/kconfig/Kconfiglib/tests/Kimply
Normal file
@ -0,0 +1,145 @@
|
||||
config MODULES
|
||||
def_bool y
|
||||
option modules
|
||||
|
||||
#
|
||||
# Implied symbols with unmet and met direct dependencies
|
||||
#
|
||||
|
||||
config IMPLY_DIRECT_DEPS
|
||||
def_tristate y
|
||||
imply UNMET_DIRECT_1
|
||||
imply UNMET_DIRECT_2
|
||||
imply UNMET_DIRECT_3
|
||||
imply MET_DIRECT_1
|
||||
imply MET_DIRECT_2
|
||||
imply MET_DIRECT_3
|
||||
imply MET_DIRECT_4
|
||||
|
||||
config UNMET_DIRECT_1
|
||||
tristate
|
||||
depends on n
|
||||
|
||||
if n
|
||||
config UNMET_DIRECT_2
|
||||
tristate
|
||||
endif
|
||||
|
||||
menu "menu"
|
||||
depends on n
|
||||
|
||||
config UNMET_DIRECT_3
|
||||
tristate
|
||||
|
||||
endmenu
|
||||
|
||||
config MET_DIRECT_1
|
||||
tristate
|
||||
|
||||
config MET_DIRECT_2
|
||||
depends on y
|
||||
tristate
|
||||
|
||||
if y
|
||||
config MET_DIRECT_3
|
||||
tristate
|
||||
endif
|
||||
|
||||
menu "menu"
|
||||
depends on y
|
||||
|
||||
config MET_DIRECT_4
|
||||
tristate
|
||||
|
||||
endmenu
|
||||
|
||||
#
|
||||
# 'imply' with condition
|
||||
#
|
||||
|
||||
config IMPLY_COND
|
||||
def_tristate y
|
||||
tristate
|
||||
imply IMPLIED_N_COND if n
|
||||
imply IMPLIED_M_COND if m
|
||||
imply IMPLIED_Y_COND if y
|
||||
|
||||
config IMPLIED_N_COND
|
||||
tristate
|
||||
|
||||
config IMPLIED_M_COND
|
||||
tristate
|
||||
|
||||
config IMPLIED_Y_COND
|
||||
tristate
|
||||
|
||||
#
|
||||
# Implying from symbol with value n
|
||||
#
|
||||
|
||||
# Will default to 'n'
|
||||
config IMPLY_N_1
|
||||
tristate
|
||||
imply IMPLIED_FROM_N_1
|
||||
|
||||
# This test also disables the imply, so it's kinda redundant, but why not
|
||||
if n
|
||||
config IMPLY_N_2
|
||||
tristate
|
||||
imply IMPLIED_FROM_N_2
|
||||
endif
|
||||
|
||||
config IMPLIED_FROM_N_1
|
||||
tristate
|
||||
|
||||
config IMPLIED_FROM_N_2
|
||||
tristate
|
||||
|
||||
#
|
||||
# Implying from symbol with value m
|
||||
#
|
||||
|
||||
config IMPLY_M
|
||||
def_tristate m
|
||||
imply IMPLIED_M
|
||||
# Implying a bool to 'm' makes it default to 'y'
|
||||
imply IMPLIED_M_BOOL
|
||||
|
||||
config IMPLIED_M
|
||||
tristate
|
||||
|
||||
config IMPLIED_M_BOOL
|
||||
bool
|
||||
|
||||
#
|
||||
# 'imply' which should raise an 'm' default to 'y'
|
||||
#
|
||||
|
||||
config IMPLY_M_TO_Y
|
||||
tristate
|
||||
default y
|
||||
imply IMPLIED_M_TO_Y
|
||||
|
||||
config IMPLIED_M_TO_Y
|
||||
tristate
|
||||
default m
|
||||
|
||||
#
|
||||
# Used for testing user values
|
||||
#
|
||||
|
||||
config DIRECT_DEP
|
||||
tristate "direct dep"
|
||||
|
||||
config IMPLY
|
||||
tristate "imply"
|
||||
imply IMPLIED_TRISTATE
|
||||
imply IMPLIED_BOOL
|
||||
|
||||
config IMPLIED_TRISTATE
|
||||
tristate "implied tristate"
|
||||
depends on DIRECT_DEP
|
||||
|
||||
config IMPLIED_BOOL
|
||||
bool "implied bool"
|
||||
depends on DIRECT_DEP
|
||||
12
scripts/kconfig/Kconfiglib/tests/Kinclude_path
Normal file
12
scripts/kconfig/Kconfiglib/tests/Kinclude_path
Normal file
@ -0,0 +1,12 @@
|
||||
config TOP
|
||||
bool
|
||||
|
||||
source "Kinclude_path_sourced_1"
|
||||
|
||||
config TOP
|
||||
bool
|
||||
|
||||
source "Kinclude_path_sourced_1"
|
||||
|
||||
config TOP
|
||||
bool
|
||||
12
scripts/kconfig/Kconfiglib/tests/Kinclude_path_sourced_1
Normal file
12
scripts/kconfig/Kconfiglib/tests/Kinclude_path_sourced_1
Normal file
@ -0,0 +1,12 @@
|
||||
config ONE_DOWN
|
||||
bool
|
||||
|
||||
source "Kinclude_path_sourced_2"
|
||||
|
||||
config ONE_DOWN
|
||||
bool
|
||||
|
||||
source "Kinclude_path_sourced_2"
|
||||
|
||||
config ONE_DOWN
|
||||
bool
|
||||
11
scripts/kconfig/Kconfiglib/tests/Kinclude_path_sourced_2
Normal file
11
scripts/kconfig/Kconfiglib/tests/Kinclude_path_sourced_2
Normal file
@ -0,0 +1,11 @@
|
||||
config TWO_DOWN
|
||||
bool
|
||||
|
||||
menu "menu"
|
||||
endmenu
|
||||
|
||||
comment "comment"
|
||||
|
||||
choice
|
||||
bool "choice"
|
||||
endchoice
|
||||
36
scripts/kconfig/Kconfiglib/tests/Kitemlists
Normal file
36
scripts/kconfig/Kconfiglib/tests/Kitemlists
Normal file
@ -0,0 +1,36 @@
|
||||
comment "comment 1"
|
||||
|
||||
choice
|
||||
bool "choice 1"
|
||||
endchoice
|
||||
|
||||
menu "menu 1"
|
||||
|
||||
choice NAMED
|
||||
bool "choice 2"
|
||||
endchoice
|
||||
|
||||
menu "menu 2"
|
||||
menu "menu 3"
|
||||
comment "comment 2"
|
||||
endmenu
|
||||
|
||||
choice
|
||||
bool "choice 3"
|
||||
endchoice
|
||||
|
||||
choice NAMED
|
||||
bool
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
menu "menu 4"
|
||||
endmenu
|
||||
|
||||
comment "comment 3"
|
||||
|
||||
endmenu
|
||||
|
||||
menu "menu 5"
|
||||
endmenu
|
||||
78
scripts/kconfig/Kconfiglib/tests/Klocation
Normal file
78
scripts/kconfig/Kconfiglib/tests/Klocation
Normal file
@ -0,0 +1,78 @@
|
||||
if UNDEFINED
|
||||
endif
|
||||
|
||||
config ONE_DEF
|
||||
bool
|
||||
|
||||
config TWO_DEF
|
||||
bool
|
||||
|
||||
config TWO_DEF
|
||||
bool
|
||||
|
||||
config MANY_DEF
|
||||
bool
|
||||
|
||||
# Throw in some line continuations too to make sure it doesn't mess up the line
|
||||
# numbers
|
||||
if y && \
|
||||
y
|
||||
if y && \
|
||||
y && \
|
||||
y
|
||||
|
||||
# Throw in some help texts too
|
||||
|
||||
config HELP_1
|
||||
bool "help 1"
|
||||
help
|
||||
config HELP_2
|
||||
bool "help 2"
|
||||
help
|
||||
foo
|
||||
bar
|
||||
|
||||
baz
|
||||
|
||||
config HELP_3
|
||||
help
|
||||
foo
|
||||
bar
|
||||
bool
|
||||
config \
|
||||
MANY_DEF
|
||||
|
||||
config MANY_DEF
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
# Expands to "tests/Klocation_sourced"
|
||||
source "$TESTS_DIR_FROM_ENV/Klocation$_SOURCED"
|
||||
|
||||
# Expands to "sub/Klocation_rsourced"
|
||||
rsource "$SUB_DIR_FROM_ENV/Klocation$_RSOURCED"
|
||||
|
||||
# Expands to "tests/*ub/Klocation_gsourced[12]", matching
|
||||
# tests/sub/Klocation_gsourced{1,2}
|
||||
source "$TESTS_DIR_FROM_ENV/*ub/Klocation$_GSOURCED[12]"
|
||||
# Test old syntax too
|
||||
gsource "$TESTS_DIR_FROM_ENV/*ub/Klocation$_GSOURCED[12]"
|
||||
|
||||
# Expands to "sub/Klocation_grsourced[12]", matching
|
||||
# tests/sub/Klocation_grsourced{1,2}
|
||||
rsource "$SUB_DIR_FROM_ENV/Klocation$_GRSOURCED[12]"
|
||||
# Test old syntax too
|
||||
grsource "$SUB_DIR_FROM_ENV/Klocation$_GRSOURCED[12]"
|
||||
|
||||
# No-ops
|
||||
osource "nonexistent"
|
||||
osource "nonexistent*"
|
||||
gsource "nonexistent"
|
||||
gsource "nonexistent*"
|
||||
orsource "nonexistent"
|
||||
orsource "nonexistent*"
|
||||
grsource "nonexistent"
|
||||
grsource "nonexistent*"
|
||||
|
||||
config MANY_DEF
|
||||
26
scripts/kconfig/Kconfiglib/tests/Klocation_sourced
Normal file
26
scripts/kconfig/Kconfiglib/tests/Klocation_sourced
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
|
||||
config MANY_DEF
|
||||
|
||||
choice CHOICE_ONE_DEF
|
||||
bool "one-def choice"
|
||||
endchoice
|
||||
|
||||
choice CHOICE_TWO_DEF
|
||||
bool "two-def choice 1"
|
||||
endchoice
|
||||
|
||||
choice CHOICE_TWO_DEF
|
||||
bool "two-def choice 2"
|
||||
endchoice
|
||||
|
||||
config MENU_HOOK
|
||||
bool
|
||||
|
||||
menu "menu"
|
||||
endmenu
|
||||
|
||||
config COMMENT_HOOK
|
||||
bool
|
||||
|
||||
comment "comment"
|
||||
5
scripts/kconfig/Kconfiglib/tests/Kmainmenu
Normal file
5
scripts/kconfig/Kconfiglib/tests/Kmainmenu
Normal file
@ -0,0 +1,5 @@
|
||||
config FOO
|
||||
string
|
||||
option env="FOO"
|
||||
|
||||
mainmenu "---$FOO---"
|
||||
37
scripts/kconfig/Kconfiglib/tests/Kmenuconfig
Normal file
37
scripts/kconfig/Kconfiglib/tests/Kmenuconfig
Normal file
@ -0,0 +1,37 @@
|
||||
# Menu nodes with is_menuconfig False
|
||||
|
||||
config NOT_MENUCONFIG_1
|
||||
bool
|
||||
|
||||
config NOT_MENUCONFIG_2
|
||||
bool "not menuconfig 2"
|
||||
|
||||
config MENUCONFIG_MULTI_DEF
|
||||
bool "menuconfig multi def 1"
|
||||
|
||||
config COMMENT_HOOK
|
||||
bool
|
||||
|
||||
comment "not menuconfig 3"
|
||||
|
||||
|
||||
# Menu nodes with is_menuconfig True
|
||||
|
||||
menuconfig MENUCONFIG_1
|
||||
bool "menuconfig 1"
|
||||
|
||||
menuconfig MENUCONFIG_MULTI_DEF
|
||||
bool "menuconfig multi def 2"
|
||||
|
||||
config MENU_HOOK
|
||||
bool
|
||||
|
||||
menu "menuconfig 2"
|
||||
endmenu
|
||||
|
||||
config CHOICE_HOOK
|
||||
bool
|
||||
|
||||
choice
|
||||
bool "menuconfig 3"
|
||||
endchoice
|
||||
82
scripts/kconfig/Kconfiglib/tests/Kmisc
Normal file
82
scripts/kconfig/Kconfiglib/tests/Kmisc
Normal file
@ -0,0 +1,82 @@
|
||||
# For testing various minor APIs
|
||||
|
||||
# optional choices
|
||||
|
||||
choice NOT_OPTIONAL
|
||||
bool "not optional"
|
||||
config A
|
||||
bool "A"
|
||||
config B
|
||||
bool "B"
|
||||
endchoice
|
||||
|
||||
choice OPTIONAL
|
||||
tristate "optional"
|
||||
optional
|
||||
config C
|
||||
tristate "C"
|
||||
config D
|
||||
tristate "D"
|
||||
# Quirky symbols - not proper choice symbol
|
||||
|
||||
config Q1
|
||||
tristate "Q1"
|
||||
depends on D
|
||||
|
||||
config Q2
|
||||
tristate "Q2"
|
||||
depends on Q1
|
||||
|
||||
config Q3
|
||||
tristate "Q3"
|
||||
depends on D
|
||||
|
||||
endchoice
|
||||
|
||||
# User values
|
||||
|
||||
config BOOL
|
||||
bool "bool" if NOT_DEFINED_1
|
||||
|
||||
config TRISTATE
|
||||
tristate # Visibility should not affect user value
|
||||
|
||||
config STRING
|
||||
string "string"
|
||||
|
||||
config INT
|
||||
int # Visibility should not affect user value
|
||||
|
||||
config HEX
|
||||
hex "hex"
|
||||
depends on NOT_DEFINED_2
|
||||
|
||||
config COMMENT_HOOK
|
||||
comment "comment"
|
||||
|
||||
config MENU_HOOK
|
||||
menu "menu"
|
||||
depends on NOT_DEFINED_3 || NOT_DEFINED_2
|
||||
depends on !NOT_DEFINED_4
|
||||
endmenu
|
||||
|
||||
config FROM_ENV
|
||||
string "from env"
|
||||
option env="ENV_VAR"
|
||||
|
||||
config FROM_ENV_MISSING
|
||||
string "from env missing"
|
||||
option env="MISSING_ENV_VAR"
|
||||
default "missing"
|
||||
|
||||
config FROM_ENV_WEIRD
|
||||
string
|
||||
default "weird"
|
||||
option env="ENV_VAR"
|
||||
|
||||
config NOT_ALLNOCONFIG_Y
|
||||
bool "not allnoconfig_y"
|
||||
|
||||
config ALLNOCONFIG_Y
|
||||
bool "allnoconfig_y"
|
||||
option allnoconfig_y
|
||||
1
scripts/kconfig/Kconfiglib/tests/Kmissingrsource
Normal file
1
scripts/kconfig/Kconfiglib/tests/Kmissingrsource
Normal file
@ -0,0 +1 @@
|
||||
rsource "nonexistent"
|
||||
1
scripts/kconfig/Kconfiglib/tests/Kmissingsource
Normal file
1
scripts/kconfig/Kconfiglib/tests/Kmissingsource
Normal file
@ -0,0 +1 @@
|
||||
source "nonexistent"
|
||||
35
scripts/kconfig/Kconfiglib/tests/Korder
Normal file
35
scripts/kconfig/Kconfiglib/tests/Korder
Normal file
@ -0,0 +1,35 @@
|
||||
config O
|
||||
int "O"
|
||||
default 0
|
||||
|
||||
config R
|
||||
int "R"
|
||||
default 1
|
||||
|
||||
config D
|
||||
int "D"
|
||||
default 2
|
||||
|
||||
config E
|
||||
int "E"
|
||||
default 3
|
||||
|
||||
# Defined twice
|
||||
config R
|
||||
int "R"
|
||||
|
||||
config R2
|
||||
int "R2"
|
||||
default 4
|
||||
|
||||
config I
|
||||
int "I"
|
||||
default 5
|
||||
|
||||
config N
|
||||
int "N"
|
||||
default 6
|
||||
|
||||
config G
|
||||
int "G"
|
||||
default 7
|
||||
151
scripts/kconfig/Kconfiglib/tests/Kpreprocess
Normal file
151
scripts/kconfig/Kconfiglib/tests/Kpreprocess
Normal file
@ -0,0 +1,151 @@
|
||||
# Simple assignments (with bad formatting, as an additional test)
|
||||
|
||||
simple-recursive=foo
|
||||
simple-immediate:=bar
|
||||
# Should become recursive
|
||||
simple-recursive-2+=baz
|
||||
|
||||
whitespaced = foo
|
||||
|
||||
|
||||
# Simple += test. += should preserve the flavor of the variable (simple vs.
|
||||
# recursive).
|
||||
|
||||
preserve-recursive = foo
|
||||
preserve-recursive += bar
|
||||
|
||||
preserve-immediate := foo
|
||||
preserve-immediate += bar
|
||||
|
||||
|
||||
# Recursive substitution
|
||||
|
||||
recursive = $(foo) $(bar) $($(b-char)a$(z-char))
|
||||
recursive += $(indir)
|
||||
|
||||
foo = abc
|
||||
bar = def
|
||||
baz = ghi
|
||||
|
||||
b-char = b
|
||||
z-char = z
|
||||
|
||||
indir = jkl $(indir-2)
|
||||
indir-2 = mno
|
||||
|
||||
|
||||
# Immediate substitution
|
||||
|
||||
def = foo
|
||||
immediate := $(undef)$(def)$(undef)$(def)
|
||||
def = bar
|
||||
undef = bar
|
||||
|
||||
|
||||
# Function calls
|
||||
|
||||
# Chained function call
|
||||
quote = "$(1)" "$(2)"
|
||||
rev-quote = $(quote,$(2),$(1))
|
||||
surround-rev-quote = $(0) $(rev-quote,$(1),$(2)) $(0)
|
||||
surround-rev-quote-unused-arg = $(surround-rev-quote,$(1),$(2)) $(3)
|
||||
# No value is passed for $(3), so it expands to nothing
|
||||
fn-indir = surround-rev-quote
|
||||
messy-fn-res = $($(fn-indir)-unused-arg, a b (,) , c d )
|
||||
|
||||
# Special characters in function call
|
||||
comma = ,
|
||||
right-paren = )
|
||||
dollar = $
|
||||
left-paren = (
|
||||
fn = "$(1)"
|
||||
special-chars-fn-res = $(fn,$(comma)$(dollar)$(left-paren)foo$(right-paren))
|
||||
|
||||
|
||||
# Variable expansions in various locations (verified by checking how the symbol
|
||||
# prints)
|
||||
|
||||
qaz = QAZ
|
||||
echo = $(1)
|
||||
ignore-first = $(2)
|
||||
|
||||
config PRINT_ME
|
||||
string "$(ENV_1)" if ($(echo,FOO) && $(echo,BAR)) || !$(echo,BAZ) || !(($(qaz)))
|
||||
default "$(echo,"foo")" if "foo $(echo,"bar") baz" = "$(undefined)"
|
||||
|
||||
# Expansion within a symbol token, with deliberate sloppiness
|
||||
config PRINT_$(ignore-first, ,ME)_TOO
|
||||
bool "foo"
|
||||
default FOO$(ignore-first, ,BAR)BAZ$(qaz) if $(qaz)&&$(qaz)FOO&&x$(ignore-first, ,xx)
|
||||
|
||||
|
||||
# Recursive expansion (throws an exception)
|
||||
|
||||
rec-1 = x $(rec-2) y
|
||||
rec-2 = x $(rec-3) y
|
||||
rec-3 = x $(rec-1) y
|
||||
|
||||
# Functions are allowed to reference themselves, but an exception is thrown if
|
||||
# the function seems to be stuck (the recursion gets too deep)
|
||||
safe-fn-rec = $($(1))
|
||||
safe-fn-rec-2 = $(safe-fn-rec,safe-fn-rec-3)
|
||||
safe-fn-rec-3 = foo
|
||||
safe-fn-rec-res = $(safe-fn-rec,safe-fn-rec-2)
|
||||
|
||||
unsafe-fn-rec = $(unsafe-fn-rec,$(1))
|
||||
|
||||
|
||||
# Expansion in the left-hand side of assignments
|
||||
|
||||
dummy-arg-fn = bar
|
||||
lhs-indir-1 = lhs-indir-2
|
||||
lhs-indir-2 = -baz
|
||||
rhs = value
|
||||
# LHS expands to foo-bar-baz
|
||||
foo-$(dummy-arg-fn, ignored argument )$($(lhs-indir-1)) = $(rhs)
|
||||
# Expands to empty string, accepted
|
||||
$(undefined)
|
||||
|
||||
# Variable with a space in its name
|
||||
empty =
|
||||
space = $(empty) $(empty)
|
||||
foo$(space)bar = value
|
||||
space-var-res = $(foo bar)
|
||||
|
||||
|
||||
# Built-in functions
|
||||
|
||||
# Expands to "baz qaz"
|
||||
shell-res = $(shell,false && echo foo bar || echo baz qaz)
|
||||
|
||||
# Warns about output on stderr, expands to nothing
|
||||
shell-stderr-res := $(shell,echo message on stderr >&2)
|
||||
|
||||
# Nested parens in macro call. Should give a single argument. Test it with
|
||||
# $(shell) to get a free argument number check.
|
||||
parens-res = pre-$(shell,echo '(a,$(b-char),(c,d),e)')-post
|
||||
|
||||
# Expands to the current location
|
||||
location-res := $(filename):$(lineno)
|
||||
|
||||
# Adds one warning, expands to nothing
|
||||
$(warning-if,,no warning)
|
||||
$(warning-if,n,no warning)
|
||||
warning-res := $(warning-if,y,a warning)
|
||||
|
||||
# Does not cause an error, expands to nothing
|
||||
error-n-res := $(error-if,n,oops)
|
||||
|
||||
# Causes an error when expanded
|
||||
error-y-res = $(error-if,y,oops)
|
||||
|
||||
|
||||
# Environment variables (for testing Kconfig.env_vars). ENV_1 is already
|
||||
# referenced above.
|
||||
env_ref_1 := xxx $(ENV_2) xxx
|
||||
env_ref_2 := $(shell,echo $(ENV_3))
|
||||
env_ref_3 :=
|
||||
env_ref_3 += $(ENV_4)
|
||||
$(warning-if,$(ENV_5),$(ENV_UNDEFINED))
|
||||
source "$(ENV_6)"
|
||||
env_ref_4 = $(ENV_7) # Never evaluated
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user