OpenWrt: Adding Patches to a Shared Library

This document explains how to:

  • Create a shared library (libbar.so)

  • Apply patches to modify its behavior

  • Export the library + headers to OpenWrt

  • Build a test application that dynamically links against the patched library

  • Install and run these components on OpenWrt

This demonstrates how OpenWrt’s patching system, shared library workflow, and dynamic linking infrastructure operate.

In this section, you are going to learn:

How to patch and build a shared library in OpenWrt?

How to export headers and shared objects into staging & rootfs?

How to build dynamic applications that link against patched libraries?

Topics in this section:

  • Step 1: Directory Layout

  • Step 1.1: Technical Notes

  • Step 2: Source Files

  • Step 2.1: Technical Notes

  • Step 3: Patch File

  • Step 3.1: Technical Notes

  • Step 4: Shared Library Makefile

  • Step 4.1: Technical Notes

  • Step 5: Build Shared Library

  • Step 5.1: Technical Notes

  • Step 6: Install Shared Library on OpenWrt VM

  • Step 6.1: Technical Notes

  • Step 7: Test Application Directory Structure

  • Step 7.1: Technical Notes

  • Step 8: Test Application Patch

  • Step 8.1: Technical Notes

  • Step 9: Test Application Makefile

  • Step 9.1: Technical Notes

  • Step 10: Build & Install Test Application

  • Step 10.1: Technical Notes

package/my/libbar/
├── Makefile
├── patches/
│   └── 0001-modify-behavior.patch
└── src/
    ├── bar.c
    └── bar.h
  • patches/ contains quilt-formatted patches.

  • All patches applied automatically via Build/Patch.

  • Shared library objects must be built with -fPIC.

bar.h

int bar_mul(int a, int b);

bar.c

#include "bar.h"
int bar_mul(int a, int b) { return a * b; }
  • bar.h exported to /usr/include.

  • bar.c patched before compile.

0001-modify-behavior.patch

--- a/bar.c
+++ b/bar.c
@@ -1,5 +1,5 @@
 int bar_mul(int a, int b) {
-    return a * b;
+    return (a * b) + 2;
 }
  • Patch modifies computation.

  • Applied before Build/Compile.

include $(TOPDIR)/rules.mk
PKG_NAME:=libbar
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk

define Package/libbar
  SECTION:=libs
  CATEGORY:=Libraries
  TITLE:=Simple shared bar library
endef

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

define Build/Compile
    $(TARGET_CC) $(TARGET_CFLAGS) -fPIC -c \
        $(PKG_BUILD_DIR)/bar.c \
        -o $(PKG_BUILD_DIR)/bar.o

    $(TARGET_CC) -shared -o $(PKG_BUILD_DIR)/libbar.so \
        $(PKG_BUILD_DIR)/bar.o
endef

define Build/InstallDev
    $(INSTALL_DIR) $(1)/usr/include
    $(INSTALL_DATA) $(PKG_BUILD_DIR)/bar.h $(1)/usr/include/

    $(INSTALL_DIR) $(1)/usr/lib
    $(INSTALL_DATA) $(PKG_BUILD_DIR)/libbar.so $(1)/usr.lib/
endef

define Package/libbar/install
    $(INSTALL_DIR) $(1)/usr/include
    $(INSTALL_DATA) $(PKG_BUILD_DIR)/bar.h $(1)/usr/include/

    $(INSTALL_DIR) $(1)/usr/lib
    $(INSTALL_DATA) $(PKG_BUILD_DIR)/libbar.so $(1)/usr/lib/
endef

$(eval $(call BuildPackage,libbar))
  • Build/Patch transforms code before compile.

  • -fPIC ensures relocatable shared object.

  • Headers + library exported to staging + rootfs.

make package/my/libbar/compile V=s
  • Result contains patched libbar.so.

  • Output placed in bin/packages/....

scp -P <PORT> libbar*.apk root@127.0.0.1:/tmp/
apk add --allow-untrusted /tmp/libbar*.apk
  • libbar.so lands in /usr/lib.

  • Patched math logic immediately active.

package/my/bar-test/
├── Makefile
├── patches/
│   └── 0001-change-message.patch
└── src/main.c
printf("bar_mul(3,5) returned %d\n", bar_mul(3,5));
  • Test program verifies shared library patching.

--- a/main.c
+++ b/main.c
@@ -5,6 +5,6 @@
 int main() {
     int result = bar_mul(3,5);
-    printf("bar_mul(3,5) returned %d\n", result);
+    printf("Patched: bar_mul(3,5) = %d\n", result);
     return 0;
 }
  • Demonstrates userland patching.

  • Logic unchanged; output modified.

DEPENDS:=+libbar

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

define Build/Compile
    $(TARGET_CC) -I$(STAGING_DIR)/usr/include \
        -L$(STAGING_DIR)/usr/lib \
        $(PKG_BUILD_DIR)/main.c \
        -lbar \
        -o $(PKG_BUILD_DIR)/bar-test
endef
  • DEPENDS ensures libbar installed first.

  • Dynamically links against patched library.

make package/my/bar-test/compile V=s
scp -P <PORT> bar-test*.apk root@127.0.0.1:/tmp/
apk add --allow-untrusted /tmp/bar-test*.apk
bar-test

Expected:

Patched: bar_mul(3,5) = 17
  • bar_mul normally returns 15 → patched to 17.

  • Dynamic linking picks up patched library without recompiling.