Skip to content
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

feat: Portable, fully-static release executables on Linux #1351

Merged
merged 10 commits into from
Feb 27, 2024
41 changes: 39 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ jobs:
kitware_key_path="/usr/share/keyrings/kitware-archive-keyring.gpg"
kitware_sources_path="/etc/apt/sources.list.d/kitware.list"

wget -O - "$kitware_key_url" 2>/dev/null | gpg --dearmor - \
curl -sL "$kitware_key_url" | gpg --dearmor - \
| sudo tee "$kitware_key_path" >/dev/null

. /etc/lsb-release # Defines $DISTRIB_CODENAME (jammy, focal, etc)
Expand Down Expand Up @@ -149,9 +149,32 @@ jobs:
export PACKAGER_LOW_MEMORY_BUILD=yes
fi

# Do fully static release builds on Linux.
BUILD_CONFIG="${{ matrix.build_type }}-${{ matrix.lib_type }}"
if [[ "${{ runner.os }}" == "Linux" && \
"$BUILD_CONFIG" == "Release-static" ]]; then
# Enable build settings for fully-static.
FULLY_STATIC="ON"

# Use a musl toolchain, since glibc static executables are not
# portable.
if [[ "${{matrix.target_arch}}" == "arm64" ]]; then
MUSL_ARCH="aarch64"
else
MUSL_ARCH="x86_64"
fi
curl -LO https://musl.cc/"$MUSL_ARCH"-linux-musl-native.tgz
tar xf "$MUSL_ARCH"-linux-musl-native.tgz
export CC=`pwd`/"$MUSL_ARCH"-linux-musl-native/bin/"$MUSL_ARCH"-linux-musl-gcc
export CXX=`pwd`/"$MUSL_ARCH"-linux-musl-native/bin/"$MUSL_ARCH"-linux-musl-g++
else
FULLY_STATIC="OFF"
fi

cmake \
-DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" \
-DBUILD_SHARED_LIBS="$BUILD_SHARED_LIBS" \
-DFULLY_STATIC="$FULLY_STATIC" \
-S . \
-B build/

Expand Down Expand Up @@ -179,7 +202,21 @@ jobs:
exit 0
fi

# TODO: Check static executables?
# Check static executables
if [[ "${{ runner.os }}" == "Linux" ]]; then
echo "::group::Check static executables"
for exe in build/packager/{packager,mpd_generator}; do
# Capture information about the executables, but also let it be
# logged to stdout.
ldd "$exe" | tee static.log
# The phrase "statically linked" means we got it right. Fail if
# we don't find it.
if ! cat static.log | grep -q statically; then
exit 1
fi
done
echo "::endgroup::"
fi

echo "::group::Prepare artifacts folder"
mkdir artifacts
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@
[submodule "packager/third_party/c-ares/source"]
path = packager/third_party/c-ares/source
url = https://github.com/c-ares/c-ares
[submodule "packager/third_party/mimalloc/source"]
path = packager/third_party/mimalloc/source
url = https://github.com/microsoft/mimalloc
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ include("packager/policies.cmake")
# Project name. May not contain spaces. Versioning is managed elsewhere.
project(shaka-packager VERSION "")

# The only build option for Shaka Packager is whether to build a shared
# libpackager library. By default, don't.
# Whether to build a shared libpackager library. By default, don't.
option(BUILD_SHARED_LIBS "Build libpackager as a shared library" OFF)

# Whether to attempt a static linking of the command line front-end.
# Only supported on Linux and with musl. This will also cause us to link
# against mimalloc to replace the standard allocator in musl, which is slow.
option(FULLY_STATIC "Attempt fully static linking of all CLI apps" OFF)

# Enable CMake's test infrastructure.
enable_testing()

Expand Down
12 changes: 12 additions & 0 deletions docs/source/build_instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ After configuring CMake you can run the build with
cmake --build build --parallel
```

To build portable, fully-static executables on Linux, you will need either musl
as your system libc, or a musl toolchain. (See [musl.cc](https://musl.cc).
To create a portable, fully-static build for Linux, configure CMake with:

```shell
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS="OFF" \
-DFULLY_STATIC="ON" \
-DCMAKE_C_COMPILER=/path/to/x86_64-linux-musl-gcc \
-DCMAKE_CXX_COMPILER=/path/to/x86_64-linux-musl-g++
```

#### Windows

Windows build instructions are similar. Using Tools > Command Line >
Expand Down
5 changes: 5 additions & 0 deletions packager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ include_directories(..)
# Public include folder, to reference public headers as packager/foo.h
include_directories(../include)

# Include settings for optional fully-static binaries.
include("fully-static.cmake")

# Include our module for gtest-based testing.
include("gtest.cmake")

Expand Down Expand Up @@ -171,6 +174,7 @@ target_link_libraries(packager
libpackager
license_notice
string_utils
${EXTRA_EXE_LIBRARIES}
)

add_executable(mpd_generator
Expand All @@ -187,6 +191,7 @@ target_link_libraries(mpd_generator
license_notice
mpd_builder
mpd_util
${EXTRA_EXE_LIBRARIES}
)

add_executable(packager_test
Expand Down
27 changes: 27 additions & 0 deletions packager/fully-static.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright 2024 Google LLC. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

# Fully-static build settings.
if(FULLY_STATIC)
# This is the "object" version of mimalloc, as opposed to the library
# version. This is important for a static override of malloc and friends.
set(EXTRA_EXE_LIBRARIES $<TARGET_OBJECTS:mimalloc-obj>)

# Keep the linker from searching for dynamic libraries.
set(CMAKE_LINK_SEARCH_START_STATIC OFF)
set(CMAKE_LINK_SEARCH_END_STATIC OFF)

# Tell CMake not to plan to relink the executables, which wouldn't make sense
# in this context and causes CMake to fail at configure time when using a
# musl toolchain for static builds.
set(CMAKE_SKIP_BUILD_RPATH ON)

# Set extra linker options necessary for fully static linking. These apply
# to all executables, which is critical when using a musl toolchain. Without
# applying these to all executables, we could create dynamic musl executables
# as intermediate outputs, which then could not run on a glibc host system.
add_link_options(-static-libgcc -static-libstdc++ -static)
endif()
1 change: 1 addition & 0 deletions packager/third_party/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ add_subdirectory(libpng EXCLUDE_FROM_ALL)
add_subdirectory(libwebm EXCLUDE_FROM_ALL)
add_subdirectory(libxml2 EXCLUDE_FROM_ALL)
add_subdirectory(mbedtls EXCLUDE_FROM_ALL)
add_subdirectory(mimalloc EXCLUDE_FROM_ALL)
add_subdirectory(mongoose EXCLUDE_FROM_ALL)
add_subdirectory(protobuf EXCLUDE_FROM_ALL)
add_subdirectory(zlib EXCLUDE_FROM_ALL)
1 change: 1 addition & 0 deletions packager/third_party/curl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ set(USE_LIBIDN2 OFF)
set(USE_LIBRTMP OFF)
set(CURL_USE_LIBSSH2 OFF)
set(CURL_ZLIB OFF CACHE STRING "Force curl not to search for system zlib")
set(BUILD_CURL_EXE OFF)

if(UNIX AND NOT APPLE)
# Use c-ares to fix static linking on Linux. Set USE_ARES directly, not the
Expand Down
2 changes: 2 additions & 0 deletions packager/third_party/libpng/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ set(PNG_BUILD_ZLIB ON)
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../zlib/source/")
# Tell libpng where to find zlib library to link to.
set(ZLIB_LIBRARY zlibstatic)
# Tell libpng where to find libm on Linux (-lm).
set(M_LIBRARY m)

# With these set in scope of this folder, load the library's own CMakeLists.txt.
add_subdirectory(source)
Expand Down
22 changes: 22 additions & 0 deletions packager/third_party/mimalloc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2024 Google LLC. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

# CMake build file to host mimalloc configuration.
# This is only used to produce static binaries on Linux, as a replacement for
# the default allocator in musl, which is slower.

# Turn these off to save time.
set(MI_BUILD_SHARED OFF)
set(MI_BUILD_STATIC OFF)
set(MI_BUILD_TESTS OFF)

# Turn these on. They are already on by default as of the date we wrote this
# file, but in case the defaults ever change, these settings are critical.
set(MI_OVERRIDE ON)
set(MI_BUILD_OBJECT ON)

# With these set in scope of this folder, load the library's own CMakeLists.txt.
add_subdirectory(source)
1 change: 1 addition & 0 deletions packager/third_party/mimalloc/source
Submodule source added at 4e50d6
Loading