OpenWrt学习(五)编译ipk hello_worlf安装包和三种编译package方式

本文详细介绍了在OpenWRT系统中制作IPK安装包的过程,包括创建源码目录、编写简单程序、构建Makefile及安装配置,适合初学者入门。

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

        openwrt 一个比较重要的特点就是它采用 ipk 包的形式安装软件。有点像是 windows 下面的安装包一样,用户只需用简单的命令就可以将 ipk 安装包安装到 openwrt 系统中,非常方便。下面来介绍如何制作编译一个简单的安装包。

源码

切换到 openwrt 源码根目录,然后执行下列命令:

cd ./package    //进入 package 目录

mkdir hello_world //创建一个名为“hello_world”的文件夹,用于放置安装包源码。

cd hello_world //进入“hello_world”目录

mkdir src //新建一个名为“src”的目录用于放置源码

vi src/hello_world.c //在 src 目录下新建一个名为 hello_world.c 文件

输入 hello_world.c 中的内容:

#include <stdio.h>
int main(char argc, char *argv[])
{
    int i = 1;
    while(1){
        //1~10 循环
        printf("Hello world!!!%d\n",i); //打印内容
		if (i < 10){
			i++;
		}else{
			i = 1;
		}
			sleep(1);// 一秒钟打印一次
	}
	return 0;
}

vi src/Makefile,//在 src 目录下新建一个 Makefile,输入下面内容:

all: hello_world
hello_world: hello_world.o
	$(CC) $(LDFLAGS) hello_world.o -o hello_world
helloworld.o: hello_world.c
	$(CC) $(CFLAGS) -c hello_world.c
clean:
	rm *.o hello_world

vi Makefile,输入下面内容:

include $(TOPDIR)/rules.mk

PKG_NAME:=hello_world
PKG_VERSION:=1.0
PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk

define Package/hello_world
	SECTION:=base
	CATEGORY:=Utilities
	TITLE:=Hello world -prints a hello world message
endef

define Package/hello_world/description
	If you can't figure out what this program does, you're probably
	brain-dead and need immediate medical attention.
endef

define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Package/hello_world/install
	$(INSTALL_DIR) $(1)/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/hello_world $(1)/bin/
endef

$(eval $(call BuildPackage,hello_world))

配置

make menuconfig,选择我们已经加进去的安装包

    Utilities  --->   

                <M> hello_world.................... Hello world -prints a hello world message

编译

make V=99

make package/hello_world/compile V=99

文件:./bin/packages/hello_world_1.0_arm.ipk

安装

scp传输到板子:

scp ./bin/packages/hello_world_1.0_arm.ipk root@192.168.10.1:/tmp

root@192.168.10.1's password: 

hello_world_1.0_arm.ipk                           100% 2279     2.2KB/s   00:00 

如提示host的key已经更改(换了其他板子):

 需要删除用户目录下的~/.ssh/known_hosts文件,重新运行scp命令进行传输。

   安装:

运行

安装路径:/bin/hello_world

扩展1、ipk包

ipk包,首先,IPK是个tar压缩包,安装其实就是通过解压到系统根目录/来完成安装的。所以,ipk的安装是覆盖安装。
也就是说,如果你之前安装过,然后自己有改动程序的话,再次安装会覆盖掉原来的文件,那你的改动就会被覆盖掉了。

解压:得到3个文件:control.tar.gz  data.tar.gz  debian-binary

[yubo.wang@localhost tmp-hello]$ tar -xvf hello_world_1.0_arm.ipk 
./debian-binary
./data.tar.gz
./control.tar.gz
  • ipk里的结构。

IPK包里首先是有3个文件,分别是:

debian-binary        ##版本信息,一般写的都是2.0……这个无关紧要……无视掉……

data.tar.gz          ##安装包的数据包,主要的安装文件都在这里,通过解压这个文件到根目录来达到安装的目的

control.tar.gz       ##安装配置文件,里面放的是安装包的配置脚本。

  • data和control这2个包。

data里的文件都是按照系统根目录来建立文件目录放至安装的程序的。这样在解压的时候就会自动的覆盖对应的文件夹和文件。

比如如果要把一个叫做test.sh的文件安装到/usr/local/bin里,那么data里的文件和文件夹夹结构就应该和安装目标是一样的:/usr/local/bin/test.sh,这样执行解压的时候就可以直接自动覆盖安装到对应的目录去了。

[yubo.wang@localhost tmp-hello]$ tar -xvzf data.tar.gz 
./
./bin/
./bin/hello_world

然后是control包,这个包里一般有preinst、postinst、prerm和postrm这几个文件。这些文件都是Linux的sh脚本,它们对应的功能是这样的:

preinst(安装前执行), postinst(安装完成执行), prerm(卸载前执行), postrm(卸载完成执行)就比如说,如果你需要在安装test.ipk安装包前删掉/tmp里的所有文件,那么你就在preinst里写sh命令rm -r /tmp/*即可。如果你需要在安装完成后输出个日志文件,你就在postinst文件里写sh命令 echo '安装完成' > /tmp/test.ipk.log即可……其他的也一样的道理。

扩展2、三种编译package方式

        1、第一种方式,Makefile,就是上面编译hello_world方式,使用源码同级目录下的Makefile文件方式,在没有实现Build/Compile情况下,通过默认的define Build/Compile/Default使用命令$(MAKE) -C $(PKG_BUILD_DIR)编译源码目录。如果自己实现就如下所示:

define Build/Compile
	$(MAKE) -C $(PKG_BUILD_DIR) \
		CC="$(TARGET_CC)" \
		CFLAGS="$(TARGET_CFLAGS) -Wall" \
		LDFLAGS="$(TARGET_LDFLAGS)"
endef

        2、第二种方式,直接gcc编译文件,使用与文件数量很少的情况下就不用去写Makefile规则:

define Build/Compile
    $(TARGET_CC) $(TARGET_CFLAGS) $(PKG_BUILD_DIR)/hello_world.c -o $(PKG_BUILD_DIR)/hello_world
endef

        如果不加$(PKG_BUILD_DIR)路径会提示:aarch64-openwrt-linux-musl-gcc: error: hello_world.c: No such file or directory,这时候还在package/hello_world目录。

        3、第三种方式,cmake,需要导入cmake.mk文件,不需实现Build/Compile。适用于网络包CMakeLists.txt情况。

include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk

<think>我们正在处理一个关于OpenWrt编译过程的问题。用户希望了解如何仅编译`build_dir`目录。根据OpenWrt编译系统,通常我们使用`make`命令来编译整个系统或特定包。但是,用户想要只编译`build_dir`目录,这实际上是一个中间目录,其中包含了编译过程中的各种临时文件目标文件。 在OpenWrt编译系统中,`build_dir`目录是自动生成的,用于存放解压后的源代码以及编译过程中生成的文件。通常,我们不会直接去编译这个目录,而是通过OpenWrt的构建系统(使用`make`命令)来触发整个编译过程,包括`build_dir`目录的生成编译。 然而,如果我们已经进行过完整的编译,现在只修改了某个包,并希望重新编译这个包(这个包对应的源代码就在`build_dir`目录下),我们可以通过指定该包的名称来重新编译它,例如: ``` make package/<package_name>/compile ``` 但是,用户的问题是“只编译build_dir目录”,这可能意味着用户希望只重新编译位于`build_dir`目录下的所有内容(即所有用户空间的包)。在OpenWrt中,我们可以通过重新编译所有用户空间包来实现,但要注意这通常不是必要的,因为通常我们只需要重新编译修改过的部分。 另外,根据引用[3]中提到的,我们可以使用类似`make target/linux/compile`这样的命令来编译特定部分。但是,对于`build_dir`目录,它实际上对应的是用户空间包的编译,因此我们可以尝试使用`make package/compile`命令来编译所有用户空间包(这些包的编译过程就是在`build_dir`目录下进行的)。 但是,需要注意的是,OpenWrt的构建系统是高度模块化的,我们通常不会直接操作`build_dir`目录。因此,直接“编译build_dir目录”并不是一个标准的操作。我们建议使用OpenWrt提供的make目标来编译特定的部分。 总结一下,如果用户希望重新编译所有用户空间包(这些包位于`build_dir`目录下),可以使用: ``` make package/compile ``` 这个命令会重新编译所有在`build_dir`目录下的用户空间包。但是,它并不会重新编译工具链或内核模块等。 另外,如果用户只是修改了某个特定的包,那么应该指定该包的名称,例如: ``` make package/example/compile ``` 这样只会重新编译名为`example`的包,其源代码位于`build_dir`目录下的对应子目录中。 因此,回答用户的问题:在OpenWrt编译系统中,没有直接“只编译build_dir目录”的命令,因为`build_dir`是一个中间目录,包含了多个包的编译内容。但是,用户可以通过`make package/compile`来重新编译所有用户空间包(这些包在`build_dir`目录下进行编译),或者通过指定包名来重新编译单个包。 注意:在重新编译之前,可能需要先清理之前的编译结果。可以使用`make package/clean`来清理所有包,或者`make package/example/clean`来清理特定包。 根据引用内容,我们还可以了解到`build_dir`目录的作用(引用[2]):它用于存放编译过程中的各种文件。因此,直接操作这个目录并不是OpenWrt构建系统设计的使用方式。 最后,我们生成相关问题。</think>### OpenWrt 编译时如何只编译 build_dir 目录 在 OpenWrt 编译系统中,`build_dir` 目录是核心编译工作区,存放所有解压后的源代码编译中间文件。要实现 **仅编译 `build_dir` 目录**,本质是重新编译用户空间的软件包而不触发完整流程(如下载、工具链编译等)。以下是具体方法: #### 1. **编译所有用户空间软件包** 执行以下命令可重新编译 `build_dir` 目录下所有已解压的软件包: ```bash make package/compile ``` - ✅ 效果:仅触发 `build_dir/` 内所有软件包的重新编译 - ✅ 不触发:工具链下载、内核编译、固件打包等阶段 - 适用场景:修改了多个软件包的源码后快速验证编译结果[^1][^3] #### 2. **编译单个软件包** 若只需编译特定软件包(如 `luci`): ```bash make package/luci/compile ``` - ✅ 路径规则:`make package/<软件包名>/compile` - ✅ 编译结果:生成在 `build_dir/` 对应子目录(如 `build_dir/target-*/<软件包名>-*`) #### 3. **清理后重新编译** 若需彻底清理某个软件包再编译: ```bash make package/luci/{clean,compile} # 先清理再编译 ``` #### 关键目录说明 | 目录 | 作用 | 是否被编译 | |------|------|------------| | `build_dir/` | 用户空间软件包源码及编译中间文件 | ✅ 通过 `make package/compile` 编译 | | `staging_dir/` | 工具链库文件(如交叉编译器) | ❌ 需通过 `make toolchain/compile` 单独编译 | | `dl/` | 下载的源码缓存 | ❌ 不参与编译 | | `bin/` | 生成的固件 | ❌ 由 `make package/install` 生成 | > **注意**:直接操作 `build_dir/` 下的文件是可行的(如修改源码),但需通过上述 `make` 命令触发编译OpenWrt 编译系统依赖顶层 `Makefile` 协调流程,不建议手动运行 `build_dir/` 内的编译脚本[^1][^2]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值