Skip to content

[build] making staticlly linked build simpler and faster #1428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/actions/muslbuilder/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
* # Ignore everything in the root context except for:

!src/third-party/prqlc-c/

!.github/actions/muslbuilder/
!.github/actions/muslbuilder/*
24 changes: 20 additions & 4 deletions .github/actions/muslbuilder/Dockerfile
Original file line number Diff line number Diff line change
@@ -161,9 +161,17 @@ RUN curl -sSL https://www.sqlite.org/2025/sqlite-autoconf-3490100.tar.gz | tar x
make install && \
cd /extract && rm -rf *

FROM --platform=$TARGETPLATFORM alpine:latest
FROM --platform=$TARGETPLATFORM alpine:latest AS rust-builder

COPY --from=depsbuilder /fake.root /fake.root
RUN apk add --no-cache \
cargo \
g++

WORKDIR /build/prqlc-c
COPY src/third-party/prqlc-c .
RUN cargo build --release --package prqlc-c

FROM --platform=$TARGETPLATFORM alpine:latest

LABEL com.github.actions.name="C++ MUSL Builder Slim"
LABEL com.github.actions.description="Provides a C++ MUSL environment"
@@ -182,5 +190,13 @@ RUN apk add --no-cache \
rust \
zip

COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

COPY --from=depsbuilder /fake.root /fake.root
COPY --from=rust-builder /build/prqlc-c/target/release/libprqlc_c.a /opt/prebuilt/libprqlc_c.a
ENV PRQLC_C_PATH=/opt/prebuilt/libprqlc_c.a
ENV LNAV_BUILD_STATIC=yes
ENV LNAV_BUILD_ENV=/fake.root
ENV PATH=/fake.root/bin:$PATH

COPY .github/actions/muslbuilder/entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
24 changes: 4 additions & 20 deletions .github/actions/muslbuilder/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,8 @@
#!/bin/sh

set -Eeuxo pipefail

if [ -z ${GITHUB_WORKSPACE:-} ]; then
git clone --depth 1 https://github.com/tstack/lnav.git
cd lnav
# If arguments are provided, execute them; otherwise, open a shell.
if [ "$#" -gt 0 ]; then
exec "$@"
else
cd ${GITHUB_WORKSPACE}
exec sh
fi

./autogen.sh
mkdir lbuild
cd lbuild
../configure \
--with-libarchive=/fake.root \
CFLAGS='-static -g1 -gz=zlib -no-pie -O2' \
CXXFLAGS='-static -g1 -gz=zlib -U__unused -no-pie -O2' \
LDFLAGS="-L/fake.root/lib" \
CPPFLAGS="-I/fake.root/include -I/fake.root/include/ncursesw" \
LIBS="-L/fake.root/lib -lssh2 -llzma -lssl -lcrypto -lz -llz4" \
--enable-static \
PATH="/fake.root/bin:${PATH}"
make -j2
16 changes: 12 additions & 4 deletions .github/workflows/bins.yml
Original file line number Diff line number Diff line change
@@ -60,7 +60,11 @@ jobs:
- name: list
run: find /fake.root
- name: make
run: /entrypoint.sh
run: >-
./autogen.sh
mkdir lbuild && cd lbuild &&
../configure --enable-release &&
make -j$(nproc)
- name: Build musl package
if: ${{ inputs.lnav_version_number != '' }}
run: >-
@@ -111,8 +115,12 @@ jobs:
uses: addnab/docker-run-action@v3
with:
image: tstack/lnav-build:latest
options: -v ${{ github.workspace }}:/lnav -e GITHUB_WORKSPACE=/lnav --platform ${{ matrix.container-platform }}
run: /entrypoint.sh
options: -v ${{ github.workspace }}:/lnav --platform ${{ matrix.container-platform }}
run: >-
./autogen.sh
mkdir lbuild && cd lbuild &&
../configure --enable-release &&
make -j$(nproc)
- name: Build musl package
if: ${{ inputs.lnav_version_number != '' }}
run: >-
@@ -171,7 +179,7 @@ jobs:
'CFLAGS=-O2 -g2' \
"LDFLAGS=-L$(brew --prefix ncurses)/lib -L$(brew --prefix xz)/lib -L$(brew --prefix zstd)/lib/ -L$(brew --prefix lz4)/lib/ -L$(brew --prefix libunistring)/lib" \
--with-libarchive=$(brew --prefix libarchive) \
"LIBS=-llzma -lzstd -liconv -llz4 -lbz2 -lz -lpcre2-8"
"LIBS= -lzstd -liconv -lbz2 -lz -lpcre2-8"
- name: make
run: make -j2
- name: Build macos package
3 changes: 1 addition & 2 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
@@ -147,11 +147,10 @@ jobs:
export PREFIX=$PWD/lnav
../lnav/configure \
--enable-static \
LDFLAGS="-static" \
CPPFLAGS="-I../src -I../../lnav/src -I../../lnav/src/fmtlib -O2 -DNCURSES_STATIC" \
CXXFLAGS="-fPIC" \
CFLAGS="-fPIC" \
LIBS="-larchive -lssh2 -llzma -llz4 -lz -lzstd -lssl -lcrypto -liconv -lunistring -lbrotlicommon -lcrypt32" \
LIBS="-larchive -lssh2 -lz -lzstd -lssl -lcrypto -liconv -lunistring -lbrotlicommon -lcrypt32" \
--sysconfdir=/etc \
--prefix=$PREFIX || cat config.log
- name: '🚧 Make (do not use -j)'
3 changes: 2 additions & 1 deletion .github/workflows/musl-build-image.yml
Original file line number Diff line number Diff line change
@@ -37,7 +37,8 @@ jobs:
name: Build and push
uses: docker/build-push-action@v4
with:
context: ${{ github.workspace }}/.github/actions/muslbuilder/
context: ${{ github.workspace }}
file: .github/actions/muslbuilder/Dockerfile
platforms: linux/amd64, linux/arm/v7, linux/arm64
push: true
tags: ${{ env.CONTAINER_TAG }}
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -197,6 +197,16 @@ $ make
$ sudo make install
```

#### Build Using Docker

To build lnav from your local source without installing all dependencies locally, use our Docker build environment by running:

```console
$ ./docker-run.sh ./autogen.sh
$ ./docker-run.sh ./configure
$ ./docker-run.sh make -j4
```

## See Also

[Angle-grinder](https://github.com/rcoh/angle-grinder) is a tool to slice and dice log files on the command-line.
96 changes: 87 additions & 9 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -71,9 +71,77 @@ AC_CHECK_FUNC(mkostemp,

AC_STRUCT_TIMEZONE

AC_ARG_ENABLE([release],
AS_HELP_STRING([--enable-release],
[Enable release features]))

AC_ARG_ENABLE([static],
AS_HELP_STRING([--enable-static],
[Enable static linking]))
AS_HELP_STRING([--enable-static],
[Enable static linking. Also accepts LNAV_BUILD_STATIC="yes" environment value]),
[],
[
if test x"${LNAV_BUILD_STATIC}" = x"yes"; then
enable_static="yes"
fi
if test x"${enable_release}" = x"yes"; then
enable_static="yes"
fi
]
)

AC_ARG_WITH([build-env],
AS_HELP_STRING(
[--with-build-env=<path>],
[Path for searching binaries, libraries, and includes. Also accepts LNAV_BUILD_ENV environment value]
),
[

if test "x$with_build_env" = "xyes"; then
AC_MSG_ERROR([--with-build-env requires a path argument])
else
if test "x$with_build_env" != "xno"; then
build_env="$with_build_env"
with_build_env="yes"
fi
fi
],
[
if test -n "$LNAV_BUILD_ENV"; then
AC_MSG_NOTICE([using LNAV_BUILD_ENV="$LNAV_BUILD_ENV"])
build_env="$LNAV_BUILD_ENV"
with_build_env="yes"
fi
]
)

if test "x$with_build_env" = "xyes"; then
LDFLAGS="-L$build_env/lib $LDFLAGS"
CPPFLAGS="-I$build_env/include -I$build_env/include/ncursesw $CPPFLAGS"
fi

if test x"${enable_release}" = x"yes"; then
CFLAGS="-g1 -gz=zlib -O2 $CFLAGS"
CXXFLAGS="-g1 -gz=zlib -O2 $CXXFLAGS"
fi

if test x"${enable_static}" = x"yes"; then
case "$host_os" in
darwin*)
STATIC_LDFLAGS="$STATIC_LDFLAGS -Wl,-search_paths_first"
;;
*)
LDFLAGS="-static $LDFLAGS"
case "$host_os" in
mingw*|cygwin*|msys*)
# Windows-like systems: do not add -no-pie.
;;
*)
LDFLAGS="-no-pie $LDFLAGS"
;;
esac
;;
esac
fi

AC_SEARCH_LIBS(openpty, util)
AC_SEARCH_LIBS(gzseek, z, [], [AC_MSG_ERROR([libz required to build])])
@@ -151,7 +219,7 @@ AS_VAR_IF([ax_cv_curses],[yes],[],
AC_MSG_ERROR([requires an X/Open-compatible Curses library with color])dnl
)

AX_PATH_LIB_ARCHIVE
AX_PATH_LIB_ARCHIVE([$enable_static])
AX_CHECK_PCRE2([8], [], [AC_MSG_ERROR([pcre2 is required to build])])

AX_CODE_COVERAGE
@@ -214,12 +282,6 @@ AS_VAR_SET(static_lib_list,
["$static_lib_list librtmp.a libiconv.a liblz4.a liblber.a libunistring.a"])

if test x"${enable_static}" = x"yes"; then
case "$host_os" in
darwin*)
STATIC_LDFLAGS="$STATIC_LDFLAGS -Wl,-search_paths_first"
;;
esac

AX_CHECK_LINK_FLAG([-static-libgcc], [STATIC_LDFLAGS="$STATIC_LDFLAGS -static-libgcc"])

STATIC_LDFLAGS="$STATIC_LDFLAGS -L`pwd`/src/static-libs"
@@ -302,6 +364,22 @@ AS_IF([test $? -eq 0],
AC_DEFINE_UNQUOTED([VCS_PACKAGE_STRING], ["$PACKAGE_STRING"], [VCS package string]))

AM_CONDITIONAL(HAVE_CARGO, test x"$CARGO_CMD" != x"")
if test x"$CARGO_CMD" != x""; then
AC_ARG_VAR([PRQLC_C_PATH], [Path to prebuilt libprqlc_c.a])
if test -n "$PRQLC_C_PATH" && test -f "$PRQLC_C_PATH"; then
rust_deps_libs_value="$PRQLC_C_PATH"
prebuilt_rust_deps=yes
else
rust_deps_libs_value="third-party/prqlc-c/target/release/libprqlc_c.a"
prebuilt_rust_deps=no
fi
else
rust_deps_libs_value=""
fi
AC_SUBST([rust_deps_libs_value])
AM_CONDITIONAL([USE_PREBUILT_RUST_DEPS], [test "$prebuilt_rust_deps" = "yes"])


AM_CONDITIONAL(HAVE_LIBCURL, test x"$LIBCURL" != x"")
AM_CONDITIONAL([CROSS_COMPILING], [ test x"$cross_compiling" != x"no" ])
AM_CONDITIONAL(HAVE_CHECK_JSONSCHEMA, test x"$CHECK_JSONSCHEMA" != x"")
29 changes: 29 additions & 0 deletions docker-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
#
# This script executes the command passed to it inside lnav's Docker build environment.
# The repository root is mounted to the container, and the working directory inside
# the container matches the current directory on the host.
#
# Usage:
# ./docker-run.sh <command> [args...]
#
# Examples:
# ./docker-run.sh ./autogen.sh # Run autogen.sh inside the container
# ./docker-run.sh ../configure --enable-release # Run configure script
# ./docker-run.sh make -j4 # Build the project
# ./docker-run.sh # Open an interactive shell in the container
#

WORKSPACE_ROOT=$(cd "$(dirname "$0")" && pwd)
CONTAINER_WS="/lnav"

# Compute the current directory's relative path to the workspace root.
RELATIVE_DIR=$(realpath --relative-to="$WORKSPACE_ROOT" "$(pwd)")
CONTAINER_WORKDIR="${CONTAINER_WS}/${RELATIVE_DIR}"

docker run -it --rm \
--user $(id -u):$(id -g) \
--volume ${WORKSPACE_ROOT}:${CONTAINER_WS} \
--workdir "${CONTAINER_WORKDIR}" \
tstack/lnav-build \
"$@"
35 changes: 16 additions & 19 deletions m4/lnav_with_libarchive.m4
Original file line number Diff line number Diff line change
@@ -29,24 +29,23 @@ dnl
dnl @file lnav_with_libarchive.m4
dnl
AC_DEFUN([AX_PATH_LIB_ARCHIVE],[dnl
AC_MSG_CHECKING([lib archive])
AC_ARG_WITH(libarchive,
[ --with-libarchive[[=prefix]]],,
with_libarchive="yes")
if test ".$with_libarchive" = ".no" ; then
AC_MSG_RESULT([disabled])
m4_ifval($2,$2)
else
AC_MSG_RESULT([(testing)])

libarchive_static=$1
if test x"$libarchive_static" = x"yes" ; then
LIBARCHIVE_REQ_LIBS="-llzma -llz4"
fi

if test ".$with_libarchive" != ".no" ; then
AC_CHECK_LIB(archive, archive_read_new)
AC_CHECK_HEADERS(archive.h)
if test "$ac_cv_lib_archive_archive_read_new" = "yes" && \
test "x$ac_cv_header_archive_h" = xyes; then
LIBARCHIVE_LIBS="-larchive"
AC_MSG_CHECKING([lib archive])
AC_MSG_RESULT([$LIBARCHIVE_LIBS])
m4_ifval($1,$1)
test "x$ac_cv_header_archive_h" = xyes ; then
LIBARCHIVE_LIBS="-larchive $LIBARCHIVE_REQ_LIBS"
else
AC_MSG_NOTICE([checking libarchive with "$with_libarchive" path considered])
unset ac_cv_header_archive_h
OLDLDFLAGS="$LDFLAGS" ; LDFLAGS="$LDFLAGS -L$with_libarchive/lib"
OLDCPPFLAGS="$CPPFLAGS" ; CPPFLAGS="$CPPFLAGS -I$with_libarchive/include"
@@ -56,20 +55,18 @@ else
LDFLAGS="$OLDLDFLAGS"
if test "$ac_cv_lib_archive_archive_read_new" = "yes" && \
test "x$ac_cv_header_archive_h" = xyes; then
AC_MSG_RESULT(.setting LIBARCHIVE_LIBS -L$with_libarchive/lib -larchive)
LIBARCHIVE_LDFLAGS="-L$with_libarchive/lib"
LIBARCHIVE_LIBS="-larchive"
LIBARCHIVE_LIBS="-larchive $LIBARCHIVE_REQ_LIBS"
test -d "$with_libarchive/include" && LIBARCHIVE_CFLAGS="-I$with_libarchive/include"
AC_MSG_CHECKING([lib archive])
AC_MSG_RESULT([$LIBARCHIVE_LIBS])
m4_ifval($1,$1)
else
AC_MSG_CHECKING([lib archive])
AC_MSG_RESULT([[no]])
m4_ifval($2,$2)
AC_MSG_NOTICE([required libarchive files not found])
fi
fi
fi

if test -n "$LIBARCHIVE_LIBS"; then
AC_MSG_NOTICE([.setting LIBARCHIVE_LIBS=$LIBARCHIVE_LIBS , LIBARCHIVE_LDFLAGS=$LIBARCHIVE_LDFLAGS , LIBARCHIVE_CFLAGS=$LIBARCHIVE_CFLAGS])
fi
AC_SUBST([LIBARCHIVE_LIBS])
AC_SUBST([LIBARCHIVE_LDFLAGS])
AC_SUBST([LIBARCHIVE_CFLAGS])
5 changes: 4 additions & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
@@ -126,14 +126,17 @@ AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS) $(USER_CXXFLAGS)
if HAVE_CARGO
RUST_DEPS_CPPFLAGS = -DHAVE_RUST_DEPS=1
PRQLC_DIR = third-party/prqlc-c/target
RUST_DEPS_LIBS = $(PRQLC_DIR)/release/libprqlc_c.a
RUST_DEPS_LIBS = @rust_deps_libs_value@
RUST_DEPS_TRIGGER = $(PRQLC_DIR)/release/libprqlc_c.a.dep

if !USE_PREBUILT_RUST_DEPS
$(RUST_DEPS_LIBS): $(srcdir)/third-party/prqlc-c/src/lib.rs $(srcdir)/third-party/prqlc-c/Cargo.toml
mkdir -p $(PRQLC_DIR)
env CARGO_TARGET_DIR=third-party/prqlc-c/target $(CARGO_CMD) build --manifest-path \
$(srcdir)/third-party/prqlc-c/Cargo.toml --package prqlc-c --release
touch $(RUST_DEPS_LIBS)
endif


else
RUST_DEPS =
Loading