# 建立編譯環境 (SDK for .ipk 封裝)

在上一篇的編譯環境中，我們建立了一個 cross-compiler，可以把原生的 c code 編譯成執行檔，並在 OpenWRT 上執行。但是，這樣的環境終究不是一個標準的開發環境，無法產生可以透過 OPKG 管理的 .ipk 套件。於是，在這一篇文章中，就介紹如何建立 SDK 環境，以及產生 .ipk 的安裝套件。

## 建立 OpenWRT SDK

![OpenWrt SDK 的建立](https://2123799480-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LNYz37Gb_OI9VBKgqqt%2F-LaZMG6o6SPOl0rvBs-j%2F-LaZMzTDLANB2myWNk1q%2Fsdk.PNG?alt=media\&token=a65a4501-4411-49da-b89c-03b7b899e0dc)

在[上一篇](https://openwrt-nctu.gitbook.io/project/openwrt-compile-env/openwrt-cross-compiler)建立 cross-compile 環境時，說明 SDK 選項不要選擇。若是勾選該選項，則會產生一個開發環境的壓縮檔，以上一篇建立的環境 (18.06版本) 為例，會出現在 openwrt 目錄下:

`bin/targets/ar71xx/generic/openwrt-sdk-ar71xx-generic_gcc-7.4.0_musl.Linux-x86_64.tar.xz`

將此檔案移出並解壓縮，我們就可以得到一個完整的 SDK 開發環境，其指令如下:

```
cp bin/targets/ar71xx/generic/openwrt-sdk-ar71xx-generic_gcc-7.4.0_musl.Linux-x86_64.tar.xz ~/sdk
cd ~/sdk/
tar xvf openwrt-sdk-ar71xx-generic_gcc-7.4.0_musl.Linux-x86_64.tar.xz
mv openwrt-sdk-ar71xx-generic_gcc-7.4.0_musl.Linux-x86_64 openwrt
```

此時，我們建立一個開發環境，目錄為: `~/sdk/openwrt` ，接著，我們轉寫一隻簡單的 helloworld.c，放在 `~/sdk/openwrt/package/hello/src` 之下。

```
#include <stdio.h>
int main()
{
    printf("This is my hello word!\n");
    return 0;
}
```

在進行套件封裝之前，我們先在`~/sdk/openwrt/package/hello/src`寫一個 Makefile 來測試 helloworld.c 的執行

```
helloworld : helloworld.o
        $(CC) $(LDFLAGS) helloworld.o -o helloworld

helloworld.o : helloworld.c
        $(CC) $(CFLAGS) -c helloworld.c

clean :
        rm *.o helloworld
```

{% hint style="info" %}
這裡要注意，在 Makefile 中，指令的開始要以 \[tab] 開始。因此，直接複製上述文字，會執行失敗。必須手動把指令前的空白改成 \[tab]， 執行 make才會成功。
{% endhint %}

執行結果如下:

```
$ make
cc  -c helloworld.c
cc  helloworld.o -o helloworld
$ ./helloworld
This is my hello word!
```

## 編譯產生 .ipk 套件

接著，我們嘗試產生一個用以產生 .ipk 套件的 Makefile，此檔案格式和  OpenWRT 系統相關，我們直接參考 OpenWRT 上的範例，並修改一下 helloworld.c 檔案所在的位置。此 Makefile 放置於 `~/sdk/openwrt/package/hello`

```
# 注意: 每行開始空格較長的為[tab]
include $(TOPDIR)/rules.mk

# Name, version and release number
# The name and version of your package are used to define the variable to point to the build directory of your package: $(PKG_BUILD_DIR)
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1

# Source settings (i.e. where to find the source codes)
# This is a custom variable, used below
SOURCE_DIR:=/home/ofwrt/sdk/openwrt/package/hello/src
# 寫入 helloworld.c 所在的資料夾

include $(INCLUDE_DIR)/package.mk

# Package definition; instructs on how and where our package will appear in the overall configuration menu ('make menuconfig')
define Package/helloworld
  SECTION:=examples
  CATEGORY:=Examples
  TITLE:=Hello, World!
endef
# 定義套件的屬性, 等一下 make menuconfig 時會用到

# Package description; a more verbose description on what our package does
define Package/helloworld/description
  A simple "Hello, world!" -application.
endef

# Package preparation instructions; create the build directory and copy the source code.
# The last command is necessary to ensure our preparation instructions remain compatible with the patching system.
define Build/Prepare
        mkdir -p $(PKG_BUILD_DIR)
        cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
        $(Build/Patch)
endef

# Package build instructions; invoke the target-specific compiler to first compile the source file, and then to link the file into the final executable
define Build/Compile
        $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/helloworld.o -c $(PKG_BUILD_DIR)/helloworld.c
        $(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/helloworld.o
endef
# 編譯後的檔案名稱, 可以隨著不同專案改變

# Package install instructions; create a directory inside the package to hold our executable, and then copy the executable we built previously into the folder
define Package/helloworld/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin
endef
# 設定透過 opkg 要安裝的位置

# This command is always the last, it uses the definitions and variables we give above in order to get the job done
$(eval $(call BuildPackage,helloworld))
```

{% hint style="info" %}
Makefile 的格式似乎會隨 OpenWRT 版本而變? 在網路上找了一些其他人的樣板，都無法順利完成，最後找到官方的樣板才解決此問題。如果用其他版本的 OpenWRT 開發可能要注意一下。
{% endhint %}

此時，整體資料結構為:

```
package
|-- hello
|   |-- Makefile (正在編輯的檔案, 用以 make .ipk 檔案)
|   `-- src
|       |-- helloworld.c
|       `-- Makefile (用以單機測試的檔案)
`-- Makefile (OpenWRT SDK )
```

接著，透過`make menuconfig`來選擇要編譯的目標:

![套件在 Example 分類下，此分類可在 Makefile 中修改](https://2123799480-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LNYz37Gb_OI9VBKgqqt%2F-LadcfpyanpC5CIIhJUB%2F-LadnSXIKSCIvhymzak8%2Fsdk-1.PNG?alt=media\&token=f4689e05-1d0d-492f-882c-81547a8ea0e6)

![將目標套件標記為M](https://2123799480-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LNYz37Gb_OI9VBKgqqt%2F-LadcfpyanpC5CIIhJUB%2F-Ladnaf1gvxIyY8TWmfw%2Fsdk-2.PNG?alt=media\&token=72a18143-27ad-4126-948a-28740cc46866)

完成後，儲存退出，接著執行: `make package/hello/compile V=99` ，以下為執行結果:

```
$ make package/hello/compile V=99
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'r8169-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'e100-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'bnx2-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'ar3k-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'mwifiex-sdio-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'kmod-phy-bcm-ns-usb2', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'edgeport-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'kmod-phy-bcm-ns-usb3', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'amdgpu-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'radeon-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'prism54-firmware', which does not exist
WARNING: Makefile 'package/linux/Makefile' has a dependency on 'rtl8192su-firmware', which does not exist
tmp/.config-package.in:36:warning: ignoring type redefinition of 'PACKAGE_libc' from 'boolean' to 'tristate'
tmp/.config-package.in:64:warning: ignoring type redefinition of 'PACKAGE_libgcc' from 'boolean' to 'tristate'
tmp/.config-package.in:149:warning: ignoring type redefinition of 'PACKAGE_libpthread' from 'boolean' to 'tristate'
#
# configuration written to .config
#
make[1]: Entering directory '/home/ofwrt/sdk/openwrt'
make[2]: Entering directory '/home/ofwrt/sdk/openwrt/package/toolchain'
echo "libc" >> /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/pkginfo/toolchain.default.install
echo "libgcc" >> /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/pkginfo/toolchain.default.install
echo "libpthread" >> /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/pkginfo/toolchain.default.install
touch -r /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/toolchain/.built /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/toolchain/.autoremove 2>/dev/null >/dev/null
find /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/toolchain -mindepth 1 -maxdepth 1 -not '(' -type f -and -name '.*' -and -size 0 ')' -and -not -name '.pkgdir' | xargs -r rm -rf
make[2]: Leaving directory '/home/ofwrt/sdk/openwrt/package/toolchain'
time: package/toolchain/compile#2.17#2.28#8.78
make[2]: Entering directory '/home/ofwrt/sdk/openwrt/package/hello'
touch /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.prepared_e3da17400d4db55e49688913f00d5372_18f1e190c5d53547fed41a3eaa76e9e9_check
mkdir -p /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0
cp /home/ofwrt/sdk/openwrt/package/hello/src/* /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0
touch /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.prepared_e3da17400d4db55e49688913f00d5372_18f1e190c5d53547fed41a3eaa76e9e9
rm -f /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.configured_*
rm -f /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/stamp/.hello_installed
(cd /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/./; if [ -x ./configure ]; then find /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ -name config.guess | xargs -r chmod u+w; find /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ -name config.guess | xargs -r -n1 cp --remove-destination /home/ofwrt/sdk/openwrt/scripts/config.guess; find /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ -name config.sub | xargs -r chmod u+w; find /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ -name config.sub | xargs -r -n1 cp --remove-destination /home/ofwrt/sdk/openwrt/scripts/config.sub; AR="mips-openwrt-linux-musl-gcc-ar" AS="mips-openwrt-linux-musl-gcc -c -Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -iremap/home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0:helloworld-1.0 -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro" LD=mips-openwrt-linux-musl-ld NM="mips-openwrt-linux-musl-gcc-nm" CC="mips-openwrt-linux-musl-gcc" GCC="mips-openwrt-linux-musl-gcc" CXX="mips-openwrt-linux-musl-g++" RANLIB="mips-openwrt-linux-musl-gcc-ranlib" STRIP=mips-openwrt-linux-musl-strip OBJCOPY=mips-openwrt-linux-musl-objcopy OBJDUMP=mips-openwrt-linux-musl-objdump SIZE=mips-openwrt-linux-musl-size CFLAGS="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -mips16 -minterlink-mips16 -iremap/home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0:helloworld-1.0 -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro " CXXFLAGS="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -mips16 -minterlink-mips16 -iremap/home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0:helloworld-1.0 -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro " CPPFLAGS="-I/home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/usr/include -I/home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/include -I/home/ofwrt/sdk/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.4.0_musl/usr/include -I/home/ofwrt/sdk/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.4.0_musl/include/fortify -I/home/ofwrt/sdk/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.4.0_musl/include " LDFLAGS="-L/home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/usr/lib -L/home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/lib -L/home/ofwrt/sdk/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.4.0_musl/usr/lib -L/home/ofwrt/sdk/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.4.0_musl/lib -znow -zrelro "   ./configure --target=mips-openwrt-linux --host=mips-openwrt-linux --build=x86_64-pc-linux-gnu --program-prefix="" --program-suffix="" --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/lib --sysconfdir=/etc --datadir=/usr/share --localstatedir=/var --mandir=/usr/man --infodir=/usr/info --disable-nls  ; fi; )
touch /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.configured_68b329da9893e34099c7d8ad5cb9c940
rm -f /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.built
touch /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.built_check
mips-openwrt-linux-musl-gcc -Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -mips16 -minterlink-mips16 -iremap/home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0:helloworld-1.0 -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -o /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/helloworld.o -c /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/helloworld.c
mips-openwrt-linux-musl-gcc -L/home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/usr/lib -L/home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/lib -L/home/ofwrt/sdk/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.4.0_musl/usr/lib -L/home/ofwrt/sdk/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.4.0_musl/lib -znow -zrelro -o /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/helloworld /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/helloworld.o
touch /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.built
rm -rf /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.pkgdir/helloworld.installed /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.pkgdir/helloworld
mkdir -p /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.pkgdir/helloworld
install -d -m0755 /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.pkgdir/helloworld/usr/bin
install -m0755 /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/helloworld /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.pkgdir/helloworld/usr/bin
touch /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.pkgdir/helloworld.installed
mkdir -p /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/root-ar71xx/stamp
SHELL= flock /home/ofwrt/sdk/openwrt/tmp/.root-copy.flock -c 'cp -fpR /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.pkgdir/helloworld/. /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/root-ar71xx/'
touch /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/root-ar71xx/stamp/.helloworld_installed
removed '/home/ofwrt/sdk/openwrt/bin/packages/mips_24kc/base/helloworld_1.0-1_mips_24kc.ipk'
mkdir -p /home/ofwrt/sdk/openwrt/bin/targets/ar71xx/generic/packages /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld/CONTROL /home/ofwrt/sdk/openwrt/staging_dir/target-mips_24kc_musl/pkginfo
install -d -m0755 /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld/usr/bin
install -m0755 /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/helloworld /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld/usr/bin
find /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld -name 'CVS' -o -name '.svn' -o -name '.#*' -o -name '*~'| xargs -r rm -rf
export CROSS="mips-openwrt-linux-musl-"  NO_RENAME=1 ; NM="mips-openwrt-linux-musl-nm" STRIP="/home/ofwrt/sdk/openwrt/staging_dir/host/bin/sstrip" STRIP_KMOD="/home/ofwrt/sdk/openwrt/scripts/strip-kmod.sh" PATCHELF="/home/ofwrt/sdk/openwrt/staging_dir/host/bin/patchelf" /home/ofwrt/sdk/openwrt/scripts/rstrip.sh /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld
rstrip.sh: /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld/usr/bin/helloworld: executable
(cd /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld/CONTROL; ( echo "$CONTROL"; printf "Description: "; echo "$DESCRIPTION" | sed -e 's,^[[:space:]]*, ,g'; ) > control; chmod 644 control; ( echo "#!/bin/sh"; echo "[ \"\${IPKG_NO_SCRIPT}\" = \"1\" ] && exit 0"; echo "[ -x "\${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; echo ". \${IPKG_INSTROOT}/lib/functions.sh"; echo "default_postinst \$0 \$@"; ) > postinst; ( echo "#!/bin/sh"; echo "[ -x "\${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; echo ". \${IPKG_INSTROOT}/lib/functions.sh"; echo "default_prerm \$0 \$@"; ) > prerm; chmod 0755 postinst prerm;  )
install -d -m0755 /home/ofwrt/sdk/openwrt/bin/packages/mips_24kc/base
/home/ofwrt/sdk/openwrt/scripts/ipkg-build -c -o 0 -g 0 /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld /home/ofwrt/sdk/openwrt/bin/packages/mips_24kc/base
Packaged contents of /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/ipkg-mips_24kc/helloworld into /home/ofwrt/sdk/openwrt/bin/packages/mips_24kc/base/helloworld_1.0-1_mips_24kc.ipk
touch -r /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.built /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0/.autoremove 2>/dev/null >/dev/null
find /home/ofwrt/sdk/openwrt/build_dir/target-mips_24kc_musl/helloworld-1.0 -mindepth 1 -maxdepth 1 -not '(' -type f -and -name '.*' -and -size 0 ')' -and -not -name '.pkgdir' | xargs -r rm -rf
make[2]: Leaving directory '/home/ofwrt/sdk/openwrt/package/hello'
time: package/hello/compile#2.05#1.96#7.92
make[1]: Leaving directory '/home/ofwrt/sdk/openwrt'
```

編譯完成後的檔案在`/sdk/openwrt/bin/packages/mips_24kc/base`目錄下，我們可以看到以下的 .ipk 檔案:

```
ofwrt@ofwrt:~/sdk/openwrt/bin/packages/mips_24kc/base$ ls
helloworld_1.0-1_mips_24kc.ipk
```

## 在 OpenWRT 上安裝 .ipk 套件

透過 OPKG 指令，我們可以在 OpenWRT 上安裝並執行所開發的 helloworld 套件，指令如下:

```
# opkg install ~/helloworld_1.0-1_mips_24kc.ipk
Installing helloworld (1.0-1) to root...
Configuring helloworld.
# helloworld
This is my hello word!
```

同樣的，原本 OPKG 支援的指令，也可以用來查詢套件的細節:

```
# opkg info helloworld
Package: helloworld
Version: 1.0-1
Depends: libc
Status: install user installed
Architecture: mips_24kc
Installed-Time: 1553342567
```

參考資料:

* <https://openwrt.org/docs/guide-developer/helloworld/start>
* <http://dvblog.soabit.com/building-custom-openwrt-packages-an-hopefully-complete-guide/>
* <https://lixingcong.github.io/2016/05/03/openwrt-helloword/>
* <https://www.cnblogs.com/tfanalysis/p/3664102.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://openwrt-nctu.gitbook.io/project/openwrt-compile-env/openwrt-sdk-and-ipk-format.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
