summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-02-05 12:31:27 +0100
committerGitHub <noreply@github.com>2021-02-05 12:31:27 +0100
commit05df7996a4c8039db0785a7e22fe8db59bcc7513 (patch)
treecfdcacee3984fc32148f83d7385e3422acfba69a
parenta4035af3375825ae277f1363c5d814ee55b92d7c (diff)
downloadopenttd-05df7996a4c8039db0785a7e22fe8db59bcc7513.tar.xz
Feature: [Actions / CMake] support for generic linux builds (#8641)
These bundles can be opened on any "modern" Linux machine with a driver that SDL2 supports. Machines needs at least glibc 2.15, which was released 10 years ago. It is build with CentOS 7 as base, and only assumes the following libraries are available on the system: - libc - libdl - libgcc_s - libpthread - librt - libstdc++ All other libraries the game depends on are bundled together with the game, so users don't need any library installed to use this bundle. The downside of course is that this increases the binary size a bit: 30 MiB of libraries are in this bundle. RPATH is used to make ld-linux find the folder libraries are stored in; however, system libraries are always used before these, in the assumption libraries on the user system are more up-to-date. Using -DOPTION_PACKAGE_DEPENDENCIES=ON switches on packaging of libraries in the "lib" folder. This requires CMake 3.16 to be installed; otherwise it will fail.
-rw-r--r--.github/workflows/release.yml91
-rw-r--r--CMakeLists.txt21
-rw-r--r--cmake/InstallAndPackage.cmake39
-rw-r--r--cmake/Options.cmake5
4 files changed, 149 insertions, 7 deletions
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4003787fc..1faaacfb3 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -265,7 +265,93 @@ jobs:
retention-days: 5
linux:
- name: Linux
+ name: Linux (Generic)
+ needs: source
+
+ runs-on: ubuntu-20.04
+ container:
+ # manylinux2014 is based on CentOS 7, but already has a lot of things
+ # installed and preconfigured. It makes it easier to build OpenTTD.
+ image: quay.io/pypa/manylinux2014_x86_64
+
+ steps:
+ - name: Download source
+ uses: actions/download-artifact@v2
+ with:
+ name: internal-source
+
+ - name: Unpack source
+ run: |
+ tar -xf source.tar.gz --strip-components=1
+
+ - name: Install dependencies
+ run: |
+ echo "::group::Install dependencies"
+ yum install -y \
+ fontconfig-devel \
+ freetype-devel \
+ libicu-devel \
+ libpng-devel \
+ libpng-devel \
+ lzo-devel \
+ SDL2-devel \
+ wget \
+ xz-devel \
+ zlib-devel \
+ # EOF
+ echo "::endgroup::"
+
+ # The yum variant of fluidsynth depends on all possible audio drivers.
+ # This is not really useful for us, as that would require a user to
+ # have them all before he can start OpenTTD. Instead, compile a
+ # version that can only use SDL2. As OpenTTD does sound via SDL2,
+ # this simply means we either have sound and music, or have none.
+ echo "::group::Install fluidsynth"
+ wget https://github.com/FluidSynth/fluidsynth/archive/v2.1.6.tar.gz
+ tar xf v2.1.6.tar.gz
+ (
+ cd fluidsynth-2.1.6
+ mkdir build
+ cd build
+ cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
+ make -j$(nproc)
+ make install
+ )
+ echo "::endgroup::"
+
+ - name: Install GCC problem matcher
+ uses: ammaraskar/gcc-problem-matcher@master
+
+ - name: Build
+ run: |
+ mkdir -p build
+ cd build
+
+ echo "::group::CMake"
+ cmake ${GITHUB_WORKSPACE} \
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+ -DOPTION_PACKAGE_DEPENDENCIES=ON \
+ # EOF
+ echo "::endgroup::"
+
+ echo "::group::Build"
+ echo "Running on $(nproc) cores"
+ make -j$(nproc) package
+ echo "::endgroup::"
+
+ # Remove the sha256 files CPack generates; we will do this ourself at
+ # the end of this workflow.
+ rm -f bundles/*.sha256
+
+ - name: Store bundles
+ uses: actions/upload-artifact@v2
+ with:
+ name: openttd-linux-generic
+ path: build/bundles
+ retention-days: 5
+
+ linux-distro:
+ name: Linux (Distros)
needs: source
if: needs.source.outputs.is_tag == 'true'
@@ -633,6 +719,7 @@ jobs:
- source
- docs
- linux
+ - linux-distro
- macos
- windows
@@ -641,7 +728,7 @@ jobs:
# "always()" is important here, it is the keyword to use to stop skipping
# this job if any dependency is skipped. It looks a bit silly, but it is
# how GitHub Actions work ;)
- if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && (needs.linux.result == 'success' || needs.linux.result == 'skipped') && needs.macos.result == 'success' && needs.windows.result == 'success'
+ if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && needs.linux.result == 'success' && (needs.linux-distro.result == 'success' || needs.linux-distro.result == 'skipped') && needs.macos.result == 'success' && needs.windows.result == 'success'
runs-on: ubuntu-20.04
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d273937a3..1ac5be5be 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -167,6 +167,27 @@ if(APPLE)
endif()
endif()
+if(OPTION_PACKAGE_DEPENDENCIES)
+ if(NOT UNIX)
+ message(FATAL_ERROR "Can only package dependencies on Linux")
+ endif()
+ if(OPTION_INSTALL_FHS)
+ message(FATAL_ERROR "Cannot install in FHS folders when we are packaging dependencies")
+ endif()
+ if(${CMAKE_VERSION} VERSION_LESS "3.16.0")
+ message(FATAL_ERROR "OPTION_PACKAGE_DEPENDENCIES can only work with CMake 3.16+; you are using ${CMAKE_VERSION}")
+ endif()
+
+ # If we are packaging dependencies, we do two things:
+ # 1) set the RPATH to include $ORIGIN/lib; $ORIGIN (that literal string)
+ # is a Linux indicator for "path where application is". In CMake, we
+ # have to do this before add_executable() is executed.
+ # 2) copy the libraries that we compile against to the "lib" folder.
+ # This is done in InstallAndPackage.cmake.
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN/lib")
+ set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
+endif()
+
include(SourceList)
# Needed by rev.cpp
diff --git a/cmake/InstallAndPackage.cmake b/cmake/InstallAndPackage.cmake
index b54c8131a..5c56d2d6d 100644
--- a/cmake/InstallAndPackage.cmake
+++ b/cmake/InstallAndPackage.cmake
@@ -123,8 +123,12 @@ elseif(UNIX)
# With FHS, we can create deb/rpm/... Without it, they would be horribly broken
# and not work. The other way around is also true; with FHS they are not
# usable, and only flat formats work.
- if(NOT OPTION_INSTALL_FHS)
+ if(OPTION_PACKAGE_DEPENDENCIES)
set(CPACK_GENERATOR "TXZ")
+ set(PLATFORM "generic")
+ elseif(NOT OPTION_INSTALL_FHS)
+ set(CPACK_GENERATOR "TXZ")
+ set(PLATFORM "unknown")
else()
find_program(LSB_RELEASE_EXEC lsb_release)
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
@@ -149,7 +153,7 @@ elseif(UNIX)
string(REGEX MATCH "ID=(.*)" _ ${OS_RELEASE_CONTENTS})
set(DISTRO_ID ${CMAKE_MATCH_1})
if(DISTRO_ID STREQUAL "arch")
- set(PLATFORM "generic")
+ set(PLATFORM "arch")
set(CPACK_GENERATOR "TXZ")
else()
set(UNSUPPORTED_PLATFORM_NAME "Linux distribution '${DISTRO_ID}' from /etc/os-release")
@@ -163,12 +167,39 @@ elseif(UNIX)
set(CPACK_GENERATOR "TXZ")
message(WARNING "Unknown ${UNSUPPORTED_PLATFORM_NAME} found for packaging; can only pack to a txz. Please consider creating a Pull Request to add support for this distribution.")
endif()
-
- set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-linux-${PLATFORM}-${CPACK_SYSTEM_NAME}")
endif()
+ set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-linux-${PLATFORM}-${CPACK_SYSTEM_NAME}")
+
else()
message(FATAL_ERROR "Unknown OS found for packaging; please consider creating a Pull Request to add support for this OS.")
endif()
include(CPack)
+
+if(OPTION_PACKAGE_DEPENDENCIES)
+ # Install all dependencies we can resolve, with the exception of ones that
+ # every Linux machine should have. This should make this build as generic
+ # as possible, where it runs on any machine with the same or newer libc
+ # than the one this is compiled with.
+ # We copy these libraries into lib/ folder, so they can be found on game
+ # startup. See comment in root CMakeLists.txt for how this works exactly.
+ install(CODE [[
+ file(GET_RUNTIME_DEPENDENCIES
+ RESOLVED_DEPENDENCIES_VAR DEPENDENCIES
+ UNRESOLVED_DEPENDENCIES_VAR UNRESOLVED_DEPENDENCIES
+ EXECUTABLES openttd
+ POST_EXCLUDE_REGEXES "ld-linux|libc.so|libdl.so|libm.so|libgcc_s.so|libpthread.so|librt.so|libstdc...so")
+ file(INSTALL
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/lib"
+ FILES ${DEPENDENCIES}
+ FOLLOW_SYMLINK_CHAIN)
+
+ # This should not be possible, but error out when a dependency cannot
+ # be resolved.
+ list(LENGTH UNRESOLVED_DEPENDENCIES UNRESOLVED_LENGTH)
+ if(${UNRESOLVED_LENGTH} GREATER 0)
+ message(FATAL_ERROR "Unresolved dependencies: ${UNRESOLVED_DEPENDENCIES}")
+ endif()
+ ]])
+endif()
diff --git a/cmake/Options.cmake b/cmake/Options.cmake
index c94a193b3..42d112790 100644
--- a/cmake/Options.cmake
+++ b/cmake/Options.cmake
@@ -44,7 +44,9 @@ endfunction()
# set_options()
#
function(set_options)
- if(UNIX AND NOT APPLE)
+ option(OPTION_PACKAGE_DEPENDENCIES "Copy dependencies into lib/ for easy packaging (Linux only)" OFF)
+
+ if(UNIX AND NOT APPLE AND NOT OPTION_PACKAGE_DEPENDENCIES)
set(DEFAULT_OPTION_INSTALL_FHS ON)
else()
set(DEFAULT_OPTION_INSTALL_FHS OFF)
@@ -76,6 +78,7 @@ endfunction()
# show_options()
#
function(show_options)
+ message(STATUS "Option Package Dependencies - ${OPTION_PACKAGE_DEPENDENCIES}")
message(STATUS "Option Dedicated - ${OPTION_DEDICATED}")
message(STATUS "Option Install FHS - ${OPTION_INSTALL_FHS}")
message(STATUS "Option Use assert - ${OPTION_USE_ASSERTS}")