|
| 1 | +# Dockerfile for Linux ARM64 cross-compilation of libgopher-mcp |
| 2 | +# Uses x64 host with aarch64-linux-gnu cross-compiler for fast builds |
| 3 | +# No QEMU emulation needed - runs at native x64 speed |
| 4 | +FROM ubuntu:20.04 |
| 5 | + |
| 6 | +# Prevent interactive prompts during package installation |
| 7 | +ENV DEBIAN_FRONTEND=noninteractive |
| 8 | + |
| 9 | +# Add ARM64 architecture for cross-compilation dependencies |
| 10 | +RUN dpkg --add-architecture arm64 |
| 11 | + |
| 12 | +# Configure repositories for cross-compilation |
| 13 | +# ARM64 packages come from ports.ubuntu.com, not archive.ubuntu.com |
| 14 | +RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main restricted universe multiverse" > /etc/apt/sources.list && \ |
| 15 | + echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal-updates main restricted universe multiverse" >> /etc/apt/sources.list && \ |
| 16 | + echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal-security main restricted universe multiverse" >> /etc/apt/sources.list && \ |
| 17 | + echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal main restricted universe multiverse" >> /etc/apt/sources.list && \ |
| 18 | + echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal-updates main restricted universe multiverse" >> /etc/apt/sources.list && \ |
| 19 | + echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal-security main restricted universe multiverse" >> /etc/apt/sources.list |
| 20 | + |
| 21 | +# Update package lists for both architectures |
| 22 | +RUN apt-get update |
| 23 | + |
| 24 | +# Install build tools (native x64) |
| 25 | +RUN apt-get install -y \ |
| 26 | + build-essential \ |
| 27 | + cmake \ |
| 28 | + pkg-config \ |
| 29 | + git \ |
| 30 | + file \ |
| 31 | + gcc-aarch64-linux-gnu \ |
| 32 | + g++-aarch64-linux-gnu \ |
| 33 | + binutils-aarch64-linux-gnu |
| 34 | + |
| 35 | +# Install ARM64 cross-compilation libraries |
| 36 | +RUN apt-get install -y \ |
| 37 | + libssl-dev:arm64 \ |
| 38 | + zlib1g-dev:arm64 \ |
| 39 | + libevent-dev:arm64 \ |
| 40 | + && rm -rf /var/lib/apt/lists/* |
| 41 | + |
| 42 | +WORKDIR /build |
| 43 | + |
| 44 | +# Copy the entire project |
| 45 | +COPY . /build/ |
| 46 | + |
| 47 | +# Create CMake toolchain file for ARM64 cross-compilation |
| 48 | +# Note: Do NOT set CMAKE_SYSROOT on Ubuntu - ARM64 libs are in multiarch paths |
| 49 | +RUN printf '%s\n' \ |
| 50 | + 'set(CMAKE_SYSTEM_NAME Linux)' \ |
| 51 | + 'set(CMAKE_SYSTEM_PROCESSOR aarch64)' \ |
| 52 | + '' \ |
| 53 | + '# Cross-compiler settings' \ |
| 54 | + 'set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)' \ |
| 55 | + 'set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)' \ |
| 56 | + 'set(CMAKE_AR aarch64-linux-gnu-ar)' \ |
| 57 | + 'set(CMAKE_RANLIB aarch64-linux-gnu-ranlib)' \ |
| 58 | + 'set(CMAKE_STRIP aarch64-linux-gnu-strip)' \ |
| 59 | + '' \ |
| 60 | + '# Target environment - where to find ARM64 libraries' \ |
| 61 | + '# Ubuntu uses multiarch paths, not a separate sysroot' \ |
| 62 | + 'set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu /usr/lib/aarch64-linux-gnu)' \ |
| 63 | + '' \ |
| 64 | + '# OpenSSL paths for ARM64' \ |
| 65 | + 'set(OPENSSL_ROOT_DIR /usr/lib/aarch64-linux-gnu)' \ |
| 66 | + 'set(OPENSSL_INCLUDE_DIR /usr/include)' \ |
| 67 | + 'set(OPENSSL_CRYPTO_LIBRARY /usr/lib/aarch64-linux-gnu/libcrypto.so)' \ |
| 68 | + 'set(OPENSSL_SSL_LIBRARY /usr/lib/aarch64-linux-gnu/libssl.so)' \ |
| 69 | + '' \ |
| 70 | + '# Search for programs in the build host directories' \ |
| 71 | + 'set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)' \ |
| 72 | + '' \ |
| 73 | + '# Search for libraries and headers in the target directories' \ |
| 74 | + 'set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)' \ |
| 75 | + 'set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)' \ |
| 76 | + 'set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)' \ |
| 77 | + '' \ |
| 78 | + '# Position independent code for shared libraries' \ |
| 79 | + 'set(CMAKE_POSITION_INDEPENDENT_CODE ON)' \ |
| 80 | + > /build/toolchain-aarch64.cmake |
| 81 | + |
| 82 | +# Create build directory and build with cross-compilation |
| 83 | +RUN mkdir -p cmake-build && cd cmake-build && \ |
| 84 | + PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig \ |
| 85 | + PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig \ |
| 86 | + cmake -DCMAKE_BUILD_TYPE=Release \ |
| 87 | + -DCMAKE_TOOLCHAIN_FILE=/build/toolchain-aarch64.cmake \ |
| 88 | + -DCMAKE_CXX_STANDARD=17 \ |
| 89 | + -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ |
| 90 | + -DBUILD_SHARED_LIBS=ON \ |
| 91 | + -DBUILD_STATIC_LIBS=ON \ |
| 92 | + -DBUILD_TESTS=OFF \ |
| 93 | + -DBUILD_C_API=ON \ |
| 94 | + -DBUILD_BINDINGS_EXAMPLES=OFF \ |
| 95 | + -DBUILD_EXAMPLES=OFF \ |
| 96 | + -DCMAKE_INSTALL_PREFIX=/build/install_prefix_dir \ |
| 97 | + -DOPENSSL_ROOT_DIR=/usr \ |
| 98 | + -DOPENSSL_INCLUDE_DIR=/usr/include \ |
| 99 | + -DOPENSSL_CRYPTO_LIBRARY=/usr/lib/aarch64-linux-gnu/libcrypto.so \ |
| 100 | + -DOPENSSL_SSL_LIBRARY=/usr/lib/aarch64-linux-gnu/libssl.so \ |
| 101 | + /build && \ |
| 102 | + make -j$(nproc) && \ |
| 103 | + make install |
| 104 | + |
| 105 | +# Create output directory and organize files |
| 106 | +RUN mkdir -p /output && \ |
| 107 | + cp /build/install_prefix_dir/lib/libgopher-mcp*.so* /output/ 2>/dev/null || true && \ |
| 108 | + cp /build/install_prefix_dir/lib/libgopher_mcp_c*.so* /output/ 2>/dev/null || true && \ |
| 109 | + cp /build/install_prefix_dir/lib/libfmt*.so* /output/ 2>/dev/null || true && \ |
| 110 | + cp /build/install_prefix_dir/lib/libllhttp*.so* /output/ 2>/dev/null || true && \ |
| 111 | + cp -r /build/install_prefix_dir/include /output/ 2>/dev/null || true |
| 112 | + |
| 113 | +# Build verification tool using cross-compiler |
| 114 | +RUN printf '%s\n' \ |
| 115 | + '#include <stdio.h>' \ |
| 116 | + '#include <dlfcn.h>' \ |
| 117 | + '#include <stdlib.h>' \ |
| 118 | + '' \ |
| 119 | + 'int main() {' \ |
| 120 | + ' printf("libgopher-mcp verification tool (Linux ARM64)\\n");' \ |
| 121 | + ' printf("==============================================\\n\\n");' \ |
| 122 | + ' void* handle = dlopen("./libgopher_mcp_c.so", RTLD_NOW);' \ |
| 123 | + ' if (!handle) {' \ |
| 124 | + ' printf("Note: C API library not found: %s\\n", dlerror());' \ |
| 125 | + ' handle = dlopen("./libgopher-mcp.so", RTLD_NOW);' \ |
| 126 | + ' if (!handle) {' \ |
| 127 | + ' printf("X Failed to load main library: %s\\n", dlerror());' \ |
| 128 | + ' return 1;' \ |
| 129 | + ' }' \ |
| 130 | + ' printf("OK Main library loaded successfully\\n");' \ |
| 131 | + ' } else {' \ |
| 132 | + ' printf("OK C API library loaded successfully\\n");' \ |
| 133 | + ' }' \ |
| 134 | + ' void* init_func = dlsym(handle, "mcp_init");' \ |
| 135 | + ' if (init_func) {' \ |
| 136 | + ' printf("OK mcp_init function found\\n");' \ |
| 137 | + ' } else {' \ |
| 138 | + ' printf("-- mcp_init function not found\\n");' \ |
| 139 | + ' }' \ |
| 140 | + ' void* cleanup_func = dlsym(handle, "mcp_cleanup");' \ |
| 141 | + ' if (cleanup_func) {' \ |
| 142 | + ' printf("OK mcp_cleanup function found\\n");' \ |
| 143 | + ' } else {' \ |
| 144 | + ' printf("-- mcp_cleanup function not found\\n");' \ |
| 145 | + ' }' \ |
| 146 | + ' dlclose(handle);' \ |
| 147 | + ' printf("\\nOK Verification complete\\n");' \ |
| 148 | + ' return 0;' \ |
| 149 | + '}' > /tmp/verify_mcp.c && \ |
| 150 | + aarch64-linux-gnu-gcc -o /output/verify_mcp /tmp/verify_mcp.c -ldl -O2 |
| 151 | + |
| 152 | +# Verify the output is actually ARM64 |
| 153 | +RUN file /output/verify_mcp && \ |
| 154 | + file /output/libgopher-mcp*.so* | head -1 |
| 155 | + |
| 156 | +# Default command to copy files to host |
| 157 | +CMD cp -r /output/* /host-output/ && \ |
| 158 | + echo "ARM64 cross-compilation complete!" && \ |
| 159 | + ls -la /output/ |
0 commit comments