deb dpkg fpm cpack debmake 打包

news2025/1/11 19:52:29

文章目录

    • deb 简介
    • hello deb
    • fpm
    • preinst postinst prerm postrm
    • cmake cpack
    • debmake

deb 简介

在这里插入图片描述

deb: Linux发行版Debian系列(如Debian, Ubuntu等)的软件包格式, 没有自提取(Self-extracting), 不能直接运行, 需要借助dpkg等安装.

Dpkg: Debian Package Manager, Debian包管理器, 中间级工具(medium-level), 用于安装, 构建, 删除和管理Debian软件包. 还有更为前端和用户友好的包管理工具, CLI(命令行接口)工具对应apt, 可以从远程获取软件包以及处理复杂的软件包关系, TUI(终端用户界面)对应aptitude, aptitude比apt又友好了一些.

hello deb

写一个 hellodeb 的程序

#!/bin/bash
cnt=0
while [ $cnt -lt 5 ]; do
    echo "Hello, DEB, $cnt"
    cnt=$((cnt+1))
done

加执行权限, 可以运行

$ chmod +x hellodeb 
$ ./hellodeb 
Hello, DEB, 0
Hello, DEB, 1
Hello, DEB, 2
Hello, DEB, 3
Hello, DEB, 4

写一个打包脚本 package.sh, 这里把安装目录设置为 /usr/bin, 放到 /usr/local/bin 也可以, 暂不考虑交叉编译(否则ARCH的值不对)

#!/bin/bash

# name of the package
PACKAGE=hellodeb
# version of the package
VERSION=1.0.0
# bionic, focal, jammy, etc.
DISTRO=$(lsb_release -cs)
# amd64 or arm64
ARCH=$(dpkg --print-architecture)

# make deb package
mkdir -p $PACKAGE-$VERSION/DEBIAN
mkdir -p $PACKAGE-$VERSION/usr/bin
cp hellodeb $PACKAGE-$VERSION/usr/bin/$PACKAGE
cat > $PACKAGE-$VERSION/DEBIAN/control << EOF
Package: $PACKAGE
Version: $VERSION
Section: base
Priority: optional
Architecture: $ARCH
Depends:
Maintainer: $USER
Description: Hello, DEB!
EOF
dpkg-deb --build $PACKAGE-$VERSION "$PACKAGE"_"$VERSION"-"$DISTRO"_"$ARCH".deb

打包, (如果走Gitlab CI, 借助Docker, 或者 Github Action等, 就可以自动打出不同Ubuntu版本等的deb包)

$ chmod +x package.sh
$ ./package.sh 

$ tree
.
├── hellodeb
├── hellodeb-1.0.0
│   ├── DEBIAN
│   │   └── control
│   └── usr
│       └── bin
│           └── hellodeb
├── hellodeb_1.0.0-focal_amd64.deb
└── package.sh

查看下包的信息和内容

# -I, --info
$ dpkg -I hellodeb_1.0.0-focal_amd64.deb 
 new Debian package, version 2.0.
 size 816 bytes: control archive=320 bytes.
     139 bytes,     8 lines      control              
 Package: hellodeb
 Version: 1.0.0
 Section: base
 Priority: optional
 Architecture: amd64
 Depends:
 Maintainer: karoto
 Description: Hello, DEB!
 
 # -c, --contents
 $ dpkg -c hellodeb_1.0.0-focal_amd64.deb 
drwxr-xr-x karoto/karoto     0 2023-01-06 13:54 ./
drwxr-xr-x karoto/karoto     0 2023-01-06 13:54 ./usr/
drwxr-xr-x karoto/karoto     0 2023-01-06 13:54 ./usr/bin/
-rwxr-xr-x karoto/karoto    94 2023-01-06 14:04 ./usr/bin/hellodeb

安装

$ sudo dpkg -i hellodeb_1.0.0-focal_amd64.deb

任意目录运行

$ hellodeb
Hello, DEB, 0
Hello, DEB, 1
Hello, DEB, 2
Hello, DEB, 3
Hello, DEB, 4

查看已安装包的信息和内容

# -s, --status
$ dpkg -s hellodeb
Package: hellodeb
Status: install ok installed
Priority: optional
Section: base
Maintainer: karoto
Architecture: amd64
Version: 1.0.0
Description: Hello, DEB!

# -L, --listfiles
$ dpkg -L hellodeb 
/.
/usr
/usr/bin
/usr/bin/hellodeb

现在我们修改源码, 升级为1.0.1版本

# hellodeb, 5->6
while [ $cnt -lt 6 ]; do
# package.sh, 1.0.0->1.0.1
VERSION=1.0.1
# 打包
$ ./package.sh
$ tree -L 1
.
├── hellodeb
├── hellodeb-1.0.0
├── hellodeb-1.0.1
├── hellodeb_1.0.0-focal_amd64.deb
├── hellodeb_1.0.1-focal_amd64.deb
└── package.sh
# 安装
sudo dpkg -i hellodeb_1.0.1-focal_amd64.deb
# 运行, 已经升到了 1.0.1
$ hellodeb 
Hello, DEB, 0
Hello, DEB, 1
Hello, DEB, 2
Hello, DEB, 3
Hello, DEB, 4
Hello, DEB, 5
# 查看安装包的简明信息
$ dpkg -l hellodeb 
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  hellodeb       1.0.1        amd64        Hello, DEB!

卸载或删除已安装的包

# -r|--remove  
$ sudo dpkg -r hellodeb

fpm

fpm, start 数挺多的, fpm的目标是使构建诸如rpms、debs、OSX包等的打包变得容易和快速

Ubuntu 上安装 fpm 及可选依赖

$ sudo gem install fpm
$ sudo apt install -y squashfs-tools
$ fpm --version
1.15.0

打包脚本就可以变为, 参数具体含义可以 fpm --help

#!/bin/bash

# name of the package
PACKAGE=hellodeb
# version of the package
VERSION=1.0.2
# bionic, focal, jammy, etc.
DISTRO=$(lsb_release -cs)
# amd64 or arm64
ARCH=$(dpkg --print-architecture)

# make deb package
fpm -f \
    -s dir \
    -t deb \
    -n $PACKAGE \
    -v $VERSION \
    -a $ARCH \
    -m $USER \
    -d "" \
    --description "HELLO, DEB!" \
    -p "$PACKAGE"_"$VERSION"-"$DISTRO"_"$ARCH".deb \
    hellodeb=/usr/local/bin/$PACKAGE

这样打出来的包也类似(多了文档)

$ dpkg -c hellodeb_1.0.2-focal_amd64.deb 
drwxr-xr-x 0/0               0 2023-01-06 14:43 ./
drwxr-xr-x 0/0               0 2023-01-06 14:43 ./usr/
drwxr-xr-x 0/0               0 2023-01-06 14:43 ./usr/share/
drwxr-xr-x 0/0               0 2023-01-06 14:43 ./usr/share/doc/
drwxr-xr-x 0/0               0 2023-01-06 14:43 ./usr/share/doc/hellodeb/
-rw-r--r-- 0/0             125 2023-01-06 14:43 ./usr/share/doc/hellodeb/changelog.gz
drwxr-xr-x 0/0               0 2023-01-06 14:43 ./usr/local/
drwxr-xr-x 0/0               0 2023-01-06 14:43 ./usr/local/bin/
-rwxr-xr-x 0/0              94 2023-01-06 14:15 ./usr/local/bin/hellodeb

preinst postinst prerm postrm

除了上面的 control 文件, 还有4个常用的文件(脚本)用于控制deb的行为:

  • preinst, 安装前运行. 如备份配置文件以免覆盖
  • postinst, 安装后运行. 如恢复配置文件, 提示是否立即运行, 提示输入用户名密码, 输入配置参数, 是否开机自启等
  • prerm, 卸载(删除)前或升级前运行. 如提示是否确认卸载, 是否保留配置文件, 备份配置文件, 停止程序运行, 关闭开机服务等
  • postrm, 卸载(删除)后或升级前运行. 如恢复配置文件, 提示山高路远江湖再见等

下面就演示一下:

$ cd testdeb/ && tree
.
├── pack.sh
└── testdeb

testdeb:

#!/bin/bash

APPNAME="testdeb"

# get NUM value from /usr/share/$APPNAME/$APPNAME.yaml or ./$APPNAME.yaml 
# if not found, set NUM=1
if [ -f "/usr/share/$APPNAME/$APPNAME.yaml" ]; then
    NUM=$(grep -E "^NUM:" /usr/share/$APPNAME/$APPNAME.yaml | awk '{print $2}')
elif [ -f "./$APPNAME.yaml" ]; then
    NUM=$(grep -E "^NUM:" ./$APPNAME.yaml | awk '{print $2}')
else
    NUM=1
fi
if [ -z "$NUM" ]; then
    NUM=1
fi

while [ $NUM -gt 0 ]; do
    echo "NUM=$NUM"
    NUM=$((NUM-1))
done

pack.sh

#!/bin/bash

PACKAGE="testdeb"
VERSION="1.0"
DISTRO=$(lsb_release -cs)
ARCH=$(dpkg --print-architecture)
CONFIG_PATH="/usr/share/$PACKAGE"
CONFIG_FILE="/usr/share/$PACKAGE/$PACKAGE.yaml"

# debian
mkdir -p $PACKAGE-$VERSION/DEBIAN
# app files
mkdir -p $PACKAGE-$VERSION/usr/bin
cp testdeb $PACKAGE-$VERSION/usr/bin/$PACKAGE
# config file, not necessary
# mkdir -p $PACKAGE-$VERSION/usr/share/$PACKAGE
# cp $PACKAGE.yaml $PACKAGE-$VERSION/usr/share/$PACKAGE/$PACKAGE.yaml

# control file
cat > $PACKAGE-$VERSION/DEBIAN/control << EOF
Package: $PACKAGE
Version: $VERSION
Section: base
Priority: optional
Architecture: $ARCH
Depends:
Maintainer: $USER
Description: Hello, TESTDEB!
EOF

# preinst file
cat > $PACKAGE-$VERSION/DEBIAN/preinst << EOF
#!/bin/bash
echo "preinst"
# bakup config file
if [ -f "$CONFIG_FILE" ]; then
    cp $CONFIG_FILE $CONFIG_FILE.bak
fi
EOF

# postinst file
cat > $PACKAGE-$VERSION/DEBIAN/postinst << EOF
#!/bin/bash
echo "postinst"
# restore config file
if [ -f "$CONFIG_FILE.bak" ]; then
    cp $CONFIG_FILE.bak $CONFIG_FILE
    rm $CONFIG_FILE.bak
fi
# get NUM value from $CONFIG_FILE
# if not found, remind user to set NUM value
NUM=\$(grep -E "^NUM:" $CONFIG_FILE | awk '{print \$2}')
if [ -z "\$NUM" ]; then
    read -p "Please set NUM value in $CONFIG_FILE: " NUM
    # NUM is a number or not, but here we don't check it
    # if CONFIG_PATH not exist, mkdir it
    if [ ! -d "$CONFIG_PATH" ]; then
        mkdir -p $CONFIG_PATH
    fi
    echo "NUM: \$NUM" > $CONFIG_FILE
fi
EOF

# prerm file
cat > $PACKAGE-$VERSION/DEBIAN/prerm << EOF
#!/bin/bash
echo "prerm"
# bakup config file
if [ -f "$CONFIG_FILE" ]; then
    cp $CONFIG_FILE $CONFIG_FILE.bak
fi
EOF

# postrm file
cat > $PACKAGE-$VERSION/DEBIAN/postrm << EOF
#!/bin/bash
echo "postrm"
# restore config file
if [ -f "$CONFIG_FILE.bak" ]; then
    cp $CONFIG_FILE.bak $CONFIG_FILE
    rm $CONFIG_FILE.bak
    # remind user to delete config file or not
    read -p "Do you want to delete $CONFIG_FILE? [y/n] " ANSWER
    if [ "\$ANSWER" == "y" ]; then
        # rm $CONFIG_FILE
        rm -rf $CONFIG_PATH
    fi
fi
EOF

# chmod
chmod +x $PACKAGE-$VERSION/usr/bin/$PACKAGE
chmod 755 $PACKAGE-$VERSION/DEBIAN/preinst
chmod 755 $PACKAGE-$VERSION/DEBIAN/postinst
chmod 755 $PACKAGE-$VERSION/DEBIAN/prerm
chmod 755 $PACKAGE-$VERSION/DEBIAN/postrm   

# make deb
dpkg-deb --build $PACKAGE-$VERSION "$PACKAGE"_"$VERSION"-"$DISTRO"_"$ARCH".deb

# delete temp dir
rm -rf $PACKAGE-$VERSION

打包安装

$ chmod +x pack.sh
$ ./pack.sh

$ sudo dpkg -i testdeb_1.0-focal_amd64.deb 
Selecting previously unselected package testdeb.
(Reading database ... 245246 files and directories currently installed.)
Preparing to unpack testdeb_1.0-focal_amd64.deb ...
preinst	# preinst打印
Unpacking testdeb (1.0) ...
Setting up testdeb (1.0) ...
postinst # postinst打印
grep: /usr/share/testdeb/testdeb.yaml: No such file or directory
Please set NUM value in /usr/share/testdeb/testdeb.yaml: 7	# 手动输入参数

# 运行
$ testdeb
NUM=7
NUM=6
NUM=5
NUM=4
NUM=3
NUM=2
NUM=1

# 卸载
$ sudo dpkg -r testdeb
(Reading database ... 245247 files and directories currently installed.)
Removing testdeb (1.0) ...
prerm
postrm
Do you want to delete /usr/share/testdeb/testdeb.yaml? [y/n] y	# 提示是否删除配置文件

cmake cpack

CMake 有 CPack 工具, 可以直接在 CMakeLists.txt 里面来设置CPACK_XXX对 install 的文件进行打包

下面是一个例子

$ cd cppdeb && tree
.
├── CMakeLists.txt
├── debian
│   ├── postinst
│   └── prerm
└── src
    └── main.cpp

src/main.cpp

#include <iostream>

int main() {
    std::cout << "Hello, CPack!" << std::endl;
    return 0;
}

debian/postinst

#!/bin/bash
echo "postinst script"

debian/prerm

#!/bin/bash
echo "prerm script"

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(cpackdebtest)

# version
set(VERSION_MAJOR 1)
set(VERSION_MINOR 0)
set(VERSION_PATCH 0)
# user
execute_process(COMMAND whoami OUTPUT_VARIABLE USER OUTPUT_STRIP_TRAILING_WHITESPACE)
# distro
execute_process(COMMAND lsb_release -cs OUTPUT_VARIABLE DISTRO OUTPUT_STRIP_TRAILING_WHITESPACE)
# arch, dpkg is required, ignore cross-compiling here
execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${USER}")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${ARCH}")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.14)")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "CPack DEB Test")

set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "${USER}")
# version
set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
# file name
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-${DISTRO}_${ARCH}")
# control file
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/debian/postinst;${CMAKE_CURRENT_SOURCE_DIR}/debian/prerm")

include(CPack)

# executable
add_executable(${PROJECT_NAME} src/main.cpp)

# install
# ${CMAKE_INSTALL_PREFIX}/bin => /usr/local/bin
# bin => /usr/bin
install(TARGETS ${PROJECT_NAME} DESTINATION bin)

打包

# mkdir build && cd build && cmake .. && make && cpack
# 或 

cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build build --target package

查看打包信息和内容

$ cd build
$ dpkg -I cpackdebtest_1.0.0-focal_amd64.deb 
 new Debian package, version 2.0.
 size 3798 bytes: control archive=403 bytes.
     215 bytes,    11 lines      control              
      55 bytes,     1 lines      md5sums              
      34 bytes,     1 lines      postinst             #!/bin/bash
      31 bytes,     1 lines      prerm                #!/bin/bash
 Architecture: amd64
 Depends: libc6 (>= 2.14)
 Description: cpackdebtest built using CMake
  CPack DEB Test
 Maintainer: karoto
 Package: cpackdebtest
 Priority: optional
 Section: devel
 Version: 1.0.0
 Installed-Size: 25
 
 $ dpkg -c cpackdebtest_1.0.0-focal_amd64.deb 
drwxr-xr-x root/root         0 2023-01-06 17:46 ./usr/
drwxr-xr-x root/root         0 2023-01-06 17:46 ./usr/bin/
-rwxr-xr-x root/root     17168 2023-01-06 17:46 ./usr/bin/cpackdebtest

安装运行与卸载

$ sudo dpkg -i cpackdebtest_1.0.0-focal_amd64.deb 
Selecting previously unselected package cpackdebtest.
(Reading database ... 245246 files and directories currently installed.)
Preparing to unpack cpackdebtest_1.0.0-focal_amd64.deb ...
Unpacking cpackdebtest (1.0.0) ...
Setting up cpackdebtest (1.0.0) ...
postinst script	# postinst 脚本

$ cpackdebtest 
Hello, CPack!

$ sudo dpkg -r cpackdebtest 
(Reading database ... 245247 files and directories currently installed.)
Removing cpackdebtest (1.0.0) ...
prerm script	#prerm 脚本

debmake

对于已有的Makefile或者CMake管理的工程, 往往不想改动或改不动任何文件, Debian 维护者指南 (这个文档要细读)中介绍的 debmake 是一个很不错的对上游源码制作Debian源代码包的程序. 也给出了很不错的示例

在这里插入图片描述

安装

sudo apt install debmake

以 linux-can/can-utils 为例, 直接去Release页面下载最新的源码包

$ mkdir can-utils && cd can-utils
# 下载存成指定的文件名格式 app-version.tar.gz
$ wget -c https://ghproxy.com/https://github.com/linux-can/can-utils/archive/refs/tags/v2021.08.0.tar.gz -O can-utils-2021.08.0.tar.gz
# 解压成指定的文件名格式 app-version
$ tar -xvf can-utils-2021.08.0.tar.gz -C can-utils-2021.08.0
$ cd can-utils-2021.08.0

# 使用debmake把源码包变成Debian源代码包
$ debmake
# 多了些文件, 主要注意多出来的 can-utils-2021.08.0/debian 文件夹中的 control 和 rules 文件
# 可以按上面 Debian 维护者指南 给的示例稍作修改, 如去掉rules文件里的一些注释, 这里不修改
# 直接debuild最后显示 Finished running lintian. 表示成功
$ debuild
# 生成的deb包为 ../can-utils_2021.08.0-1_amd64.deb
$ cd ..

# 查看包信息
$ sudo dpkg -I can-utils_2021.08.0-1_amd64.deb
 new Debian package, version 2.0.
 size 123808 bytes: control archive=1412 bytes.
     379 bytes,    13 lines      control
    1834 bytes,    34 lines      md5sums
 Package: can-utils
 Version: 2021.08.0-1
 Architecture: amd64
 Maintainer: <>
 Installed-Size: 732
 Depends: libc6 (>= 2.17)
 Section: unknown
 Priority: optional
 Multi-Arch: foreign
 Homepage: <insert the upstream URL, if relevant>
 Description: auto-generated package by debmake
  This Debian binary package was auto-generated by the
  debmake(1) command provided by the debmake package.

# 查看包内容
$ sudo dpkg -c can-utils_2021.08.0-1_amd64.deb
drwxr-xr-x root/root         0 2023-01-06 18:16 ./
drwxr-xr-x root/root         0 2023-01-06 18:16 ./usr/
drwxr-xr-x root/root         0 2023-01-06 18:16 ./usr/bin/
-rwxr-xr-x root/root     31088 2023-01-06 18:16 ./usr/bin/asc2log
-rwxr-xr-x root/root     14488 2023-01-06 18:16 ./usr/bin/bcmserver
-rwxr-xr-x root/root     22320 2023-01-06 18:16 ./usr/bin/can-calc-bit-timing
-rwxr-xr-x root/root     18584 2023-01-06 18:16 ./usr/bin/canbusload
-rwxr-xr-x root/root     35184 2023-01-06 18:16 ./usr/bin/candump
-rwxr-xr-x root/root     14496 2023-01-06 18:16 ./usr/bin/canfdtest
-rwxr-xr-x root/root     31088 2023-01-06 18:16 ./usr/bin/cangen
-rwxr-xr-x root/root     26776 2023-01-06 18:16 ./usr/bin/cangw
-rwxr-xr-x root/root     31088 2023-01-06 18:16 ./usr/bin/canlogserver
-rwxr-xr-x root/root     31088 2023-01-06 18:16 ./usr/bin/canplayer
-rwxr-xr-x root/root     22896 2023-01-06 18:16 ./usr/bin/cansend
-rwxr-xr-x root/root     14832 2023-01-06 18:16 ./usr/bin/cansequence
-rwxr-xr-x root/root     26816 2023-01-06 18:16 ./usr/bin/cansniffer
-rwxr-xr-x root/root     22680 2023-01-06 18:16 ./usr/bin/isotpdump
-rwxr-xr-x root/root     18584 2023-01-06 18:16 ./usr/bin/isotpperf
-rwxr-xr-x root/root     14488 2023-01-06 18:16 ./usr/bin/isotprecv
-rwxr-xr-x root/root     14488 2023-01-06 18:16 ./usr/bin/isotpsend
-rwxr-xr-x root/root     18584 2023-01-06 18:16 ./usr/bin/isotpserver
-rwxr-xr-x root/root     18584 2023-01-06 18:16 ./usr/bin/isotpsniffer
-rwxr-xr-x root/root     18616 2023-01-06 18:16 ./usr/bin/isotptun
-rwxr-xr-x root/root     22984 2023-01-06 18:16 ./usr/bin/j1939acd
-rwxr-xr-x root/root     18584 2023-01-06 18:16 ./usr/bin/j1939cat
-rwxr-xr-x root/root     18856 2023-01-06 18:16 ./usr/bin/j1939spy
-rwxr-xr-x root/root     18888 2023-01-06 18:16 ./usr/bin/j1939sr
-rwxr-xr-x root/root     31088 2023-01-06 18:16 ./usr/bin/log2asc
-rwxr-xr-x root/root     18800 2023-01-06 18:16 ./usr/bin/log2long
-rwxr-xr-x root/root     34968 2023-01-06 18:16 ./usr/bin/mcp251xfd-dump
-rwxr-xr-x root/root     14488 2023-01-06 18:16 ./usr/bin/slcan_attach
-rwxr-xr-x root/root     18592 2023-01-06 18:16 ./usr/bin/slcand
-rwxr-xr-x root/root     18584 2023-01-06 18:16 ./usr/bin/slcanpty
-rwxr-xr-x root/root     18584 2023-01-06 18:16 ./usr/bin/testj1939
drwxr-xr-x root/root         0 2023-01-06 18:16 ./usr/share/
drwxr-xr-x root/root         0 2023-01-06 18:16 ./usr/share/doc/
drwxr-xr-x root/root         0 2023-01-06 18:16 ./usr/share/doc/can-utils/
-rw-r--r-- root/root       203 2023-01-06 18:16 ./usr/share/doc/can-utils/README.Debian
-rw-r--r-- root/root       167 2023-01-06 18:16 ./usr/share/doc/can-utils/changelog.Debian.gz
-rw-r--r-- root/root     34841 2023-01-06 18:16 ./usr/share/doc/can-utils/copyright

如果修改了某些东西

# 修改 candump.c 30=>300
#define MAXIFNAMES 300

# 再构建会报错
$ debuild
dpkg-source: info: local changes detected, the modified files are:
 can-utils-2021.08.0/candump.c
dpkg-source: error: aborting due to unexpected upstream changes, see /tmp/can-utils_2021.08.0-1.diff.t16td_
dpkg-source: info: you can integrate the local changes with dpkg-source --commit
dpkg-buildpackage: error: dpkg-source -b . subprocess returned exit status 2
debuild: fatal error at line 1182:
dpkg-buildpackage -us -uc -ui failed

# 提示文件更改了, 需要运行一下 dpkg-source --commit 命令
$ dpkg-source --commit
dpkg-source: info: local changes detected, the modified files are:
 can-utils-2021.08.0/candump.c
Enter the desired patch name: I modify candump file MAXIFNAMES define	# 这里输入一个patch的名字
# patch 名字输入完后会自动打开这个patch的内容, 一般是 nano 或 vi 编辑器, 后者输入 :q 退出来即可
dpkg-source: info: local changes have been recorded in a new patch: can-utils-2021.08.0/debian/patches/I-modify-candump-file-MAXIFNAMES-define

# patch的位置 can-utils/can-utils-2021.08.0/debian/patches/I-modify-candump-file-MAXIFNAMES-define
# 可以直接看这个文件, 类似 git diff 样式的显示
$ cat debian/patches/I-modify-candump-file-MAXIFNAMES-define
...
-#define MAXIFNAMES 30 /* size of receive name index to omit ioctls */
+#define MAXIFNAMES 300 /* size of receive name index to omit ioctls */

# 之后就可以构建了
$ debuild
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/146116.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python读取各种形式文件(excel,txt),python基本用法

读取excel,读取结果是dataframe形式。 excelFile ranalyze_search_category.xlsx df pd.DataFrame(pd.read_excel(excelFile)) print(df) 详情&#xff1a;(21条消息) 在Python中使用Pandas.DataFrame对Excel操作笔记一 - 从Excel里面获取说需要的信息_fengqiaoxian的博客-CS…

TensorFlow之模型保存与加载

模型在训练过程中或者在训练之后&#xff0c;模型的执行过程能被保存&#xff0c;也就是&#xff0c;模型能从暂停中恢复以免训练的时间过长。因此&#xff0c;被保存的模型可以被共享&#xff0c;其他人可以重新构建相同的模型。被保存的模型以如下的两种方式进行共享&#xf…

青训营——前端方向练习题(不定项选择题例题)

文章目录 &#x1f4c4;前言 PART1 PART2 PART3 PART4 PART5 PART6 PART7 PART8 PART9 &#x1f4c4;前言 一共有十八题&#xff0c;题目选项为不定项&#xff0c;有单选&#xff0c;也有多选。 PART1 选择题 1&#xff1a; 下列哪些是 HTML5 的新特性&#xff1f; A…

Android 深入系统完全讲解(3)

3 Zygote 虚拟机的流程&#xff0c;学习方法 说完了 init 的启动过程&#xff0c;我们来说说 Zygote 的启动过程。 这里我们看下整个的步骤&#xff0c;主要完成了&#xff1a; 1 startVM() 创建虚拟机 2 startReg() 注册 JNI 方法 3 preload()预加载通用类&#xff0c;这里主…

【信管7.1】质量与质量管理过程

质量与质量管理过程对于我们的项目管理理论相关的学习来说&#xff0c;质量是除了范围、进度、成本之外的另一个核心内容。还记得我们在学习敏捷的时候讲过的项目管理三角形吗&#xff1f;通过之前的课程&#xff0c;我们已经学完了它的三个支点。接下来&#xff0c;我们就要学…

播客丨关于年终总结,程序员有话说

绘声绘影绘声绘影是网易云信独家打造的一档聚焦行业热点、个人成长方面的播客栏目。栏目希望通过邀请不同背景、不同行业、不同阅历的企业研发、产品、运营等相关岗位负责人作为节目嘉宾&#xff0c;以自身职业视角交流行业洞见和发展前景&#xff1b;以过来人的视角分享在时代…

dfs、bfs搜索题型小结

一、全排列 &#xff08;1&#xff09;1199&#xff1a;全排列 原题链接 解析 &#xff08;2&#xff09;剪枝思想 满足等式关系的全排列——dfs剪枝 &#xff08;3&#xff09;P1088 [NOIP2004 普及组] 火星人 原题链接 解析 二、组合&#xff08;选与不选&#xff09;…

web(四)—— CSS基础(选择器进阶、Emmet语法、背景属性、元素显示模式、三大特性)

一、选择器进阶目标&#xff1a;能够理解 复合选择器 的规则&#xff0c;并使用 复合选择器 在 HTML 中选择元素1. 复合选择器1.1 后代选择器&#xff1a;空格作用&#xff1a;根据 HTML 标签的嵌套关系&#xff0c;选择父元素 后代中 满足条件的元素 选择器语法&#xff1a;选…

Maven的安装配置与基本使用

Maven简介&#xff1a; Maven是专门用于管理和构建java项目的工具&#xff0c;它的主要功能有&#xff1a; 提供了一套标准化的项目结构标准化的项目结构&#xff1a; Maven提供了一套标准化的项目结构&#xff0c;所有的IDE使用Maven构建的项目结构完全一样&#xff0c;所有…

【IEEE出版社】人工智能、数据挖掘、机器人、传感等领域SCI,自引率低,对国人友好,评职毕业高分好刊~

1区人工智能类SCI&EI 【出版社】IEEE 【自引率】4.30%&#xff08;低&#xff09; 【国人占比】13.40% 【期刊简介】IF:6.5-7.0&#xff0c;JCR1区&#xff0c;中科院3区 【检索情况】SCI&EI 双检&#xff0c;正刊 【参考周期】3-5个月左右录用 【截稿日期】202…

如何彻底关闭Win10自动更新,Win10永久关闭自动更新的方法

如何彻底关闭Win10自动更新&#xff1f;Win10自动更新的问题是很多用户都遇到的问题&#xff0c;很多时候我们关闭了自动更新&#xff0c;过一段时间系统又自动更新了&#xff0c;由于win10自动更新非常顽固&#xff0c;所以我们要从多个地方下手才能永久关闭其自动更新&#x…

Java中几种常量池的区分

文章目录前言了解一下 ldc 指令字符串常量池在 Java 内存区域的哪个位置1.全局字符串池&#xff08;string pool也有叫做string literal pool&#xff09;2.class文件常量池&#xff08;class constant pool&#xff09;3.运行时常量池&#xff08;runtime constant pool&#…

干货 | Python的面试题目+答案合集

作为一个 Python 新手&#xff0c;你必须熟悉基础知识。 在本期内容中我们将讨论一些 Python 面试的基础问题和高级问题以及答案&#xff0c;以帮助你完成面试。 包括 Python 开发问题、编程问题、数据结构问题、和 Python 脚本问题。 接下来让我们来深入研究这些问题 Pytho…

AD转换芯片精度计算及校正方法

文章目录前言一、转换精度二、重要参数1.线性误差&#xff08;INL&#xff09;和差分线性误差&#xff08;DNL&#xff09;2.失调误差和增益误差三、转换校正总结前言 本文对模数转换芯片的精度进行简要介绍&#xff0c;帮助大家正确选型&#xff0c;并介绍了一个基本的ADC转换…

postgresql13+postgis3.2安装教程

postgresql13postgis3.2安装教程 安装postgresql13 安装pg13 pg13安装包 cd /home/soft/pg tar -zxvf postgresql-13.6.tar.gz cd postgresql-13.6# yum -y install -y readline-devel./configure --prefix/usr/local/pgsqlmake -j4make install设置环境变量 vim /etc/pr…

OpenGPT的11种高效用法

1. 问答提示 2. 解释复杂的概念 3. 创作 创作需要尽可能的缩小范围&#xff0c;提出具体的要求&#xff0c;AI会给出更好的答案。 4. 准备面试 5. 教师教案 6. 编码和集成 7. 健身 8. 送礼推荐 9. 翻译 这个甚至不用去演示&#xff0c;openAI的翻译能力非常强大&#xff0c…

计算机专业混子应届生,如何3个月逆袭,成功上岸?

在我进入大学之前&#xff0c;我一直对计算机感兴趣。虽然只是考了一个一般大学&#xff0c;但是选专业的时候还是选了计算机专业。 本来以为自己会在大学里学到很多有用的知识&#xff0c;并且能够很快找到一份好工作。但是&#xff0c;事实并不是这样。在大学期间&#xff0c…

竞品分析:叮咚买菜

​生鲜包括了三类未加工的初级产品“果蔬&#xff08;水果蔬菜&#xff09;、肉类、水产品”以及两类加工产品“面包和熟食”。熟食又包括“冷藏的冷冻食品、乳制品和非冷藏的散装杂粮”。 生鲜电商就是以电子商务的形式销售以上产品。 生鲜电商有着“悠久”的历史&#xff0…

Vue组件的生命周期

一、生命周期 & 生命周期函数 1. 生命周期&#xff08;Life Cycle&#xff09;是指一个组件从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 2. 生命周期函数&#xff1a;是由 vue 框架提供的内置函数&#xff0c;会伴随着组件的生命周期&#xf…

第四十三讲:神州防火墙混合模式的初始配置

混合模式即相当于防火墙既工作于路由模式&#xff0c;又工作于透明模式。在实际应用环境中&#xff0c;此类防火墙应用一般也比较广泛。混合模式分为两种&#xff1a; 一&#xff0c;ISP分配外网地址&#xff0c;内网为私网地址&#xff0c;服务器区域和内部地址为同一网段。这…