diff --git a/debian/control b/debian/control index b9f81d65f8a9a75b9072ca1e7ae44ee50860911f..43b1bec67f32cd95d5d79abf0efeec886b4d4f39 100644 --- a/debian/control +++ b/debian/control @@ -57,6 +57,21 @@ Description: Steam Runtime utility library - shared library . This package contains the shared library. +Package: libsteam-runtime-tools-0-helpers +Architecture: amd64 i386 +Multi-Arch: same +Section: misc +Depends: + ${misc:Depends}, + ${shlibs:Depends}, +Description: + The Steam Runtime is the library stack used to run the Steam client + on Linux. The Steam Runtime Tools utility library contains open-source + supporting code used by the Steam client to discover system information. + . + This package contains helper tools used to examine the library stack + available for each architecture. + Package: libsteam-runtime-tools-0-tests Architecture: any Section: misc diff --git a/debian/libsteam-runtime-tools-0-helpers.install b/debian/libsteam-runtime-tools-0-helpers.install new file mode 100644 index 0000000000000000000000000000000000000000..4d24bb6e601f5ae39446eb84d572b5f5947a1614 --- /dev/null +++ b/debian/libsteam-runtime-tools-0-helpers.install @@ -0,0 +1 @@ +usr/libexec/steam-runtime-tools-0/* diff --git a/helpers/meson.build b/helpers/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..386c962b12f672f2e02cbe6f215d4edc42bb4afd --- /dev/null +++ b/helpers/meson.build @@ -0,0 +1,34 @@ +# Copyright © 2019 Collabora Ltd. +# +# SPDX-License-Identifier: MIT +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +executable( + multiarch + '-true', + 'true.c', + install : true, + install_dir : join_paths( + get_option('libexecdir'), + 'steam-runtime-tools-' + api_major, + ) +) + +# vim:set sw=2 sts=2 et: diff --git a/helpers/true.c b/helpers/true.c new file mode 100644 index 0000000000000000000000000000000000000000..57c891fc915389b53d367e1953ddf876994755fc --- /dev/null +++ b/helpers/true.c @@ -0,0 +1,35 @@ +/* + * Copyright © 2019 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * This is basically /bin/true. We have it so that we can compile it for + * multiple CPU architectures, and check which ones we can run. + */ +int +main (int argc, + char **argv) +{ + return 0; +} diff --git a/meson.build b/meson.build index 92901f6b5cc6d73d19c928bb44366fbf5542f905..0c9603a03132afde727aecc0864170e2582b706f 100644 --- a/meson.build +++ b/meson.build @@ -103,7 +103,20 @@ gobject = dependency( ) project_include_dirs = include_directories('.') +if host_machine.cpu_family() == 'x86_64' + multiarch = 'x86_64-linux-gnu' +elif host_machine.cpu_family() == 'x86' + multiarch = 'i386-linux-gnu' +else + multiarch = '' +endif + subdir('steam-runtime-tools') + +if multiarch != '' + subdir('helpers') +endif + subdir('docs') subdir('examples') subdir('tests') diff --git a/steam-runtime-tools/architecture.c b/steam-runtime-tools/architecture.c index 523b7203c7f311920fea935af75e224cd6810709..841c13af65a22ade8175be5e634be34b5231a1cc 100644 --- a/steam-runtime-tools/architecture.c +++ b/steam-runtime-tools/architecture.c @@ -25,24 +25,136 @@ #include "steam-runtime-tools/architecture.h" +#include <dlfcn.h> +#include <link.h> +#include <string.h> + +static gchar *helpers_path = NULL; + +static const char * +_srt_get_helpers_path (void) +{ + const char *path; + void *handle = NULL; + struct link_map *map = NULL; + + path = helpers_path; + + if (path != NULL) + goto out; + + path = g_getenv ("SRT_HELPERS_PATH"); + + if (path != NULL) + goto out; + + handle = dlopen (NULL, RTLD_LAZY|RTLD_GLOBAL); + + if (handle == NULL) + { + g_warning ("Unable to dlopen self: %s", dlerror ()); + goto out; + } + + if (dlinfo (handle, RTLD_DI_LINKMAP, &map) != 0) + { + g_warning ("dlinfo RTLD_DI_LINKMAP: %s", dlerror ()); + goto out; + } + + while (map != NULL && map->l_prev != NULL) + map = map->l_prev; + + for (; map != NULL; map = map->l_next) + { + g_debug ("%s", map->l_name); + + if (g_str_has_suffix (map->l_name, "/" _SRT_SONAME)) + { + gchar *dir = g_path_get_dirname (map->l_name); + + if (g_str_has_suffix (dir, "/" _SRT_MULTIARCH)) + dir[strlen (dir) - strlen ("/" _SRT_MULTIARCH)] = '\0'; + + if (g_str_has_suffix (dir, "/lib")) + dir[strlen (dir) - strlen ("/lib")] = '\0'; + + /* deliberate one-per-process leak */ + helpers_path = g_build_filename ( + dir, "libexec", "steam-runtime-tools-" _SRT_API_MAJOR, + NULL); + path = helpers_path; + + g_free (dir); + break; + } + } + +out: + if (handle != NULL) + dlclose (handle); + + /* We have to return *something* non-NULL */ + if (path == NULL) + { + g_warning ("Unable to determine path to helpers"); + path = "/"; + } + + return path; +} + +static gboolean +_srt_architecture_can_run (const char *multiarch) +{ + gchar *helper = NULL; + const gchar *argv[] = { "true", NULL }; + int exit_status = -1; + GError *error = NULL; + gboolean ret = FALSE; + + helper = g_strdup_printf ("%s/%s-true", + _srt_get_helpers_path (), multiarch); + argv[0] = helper; + g_debug ("Testing architecture %s with %s", multiarch, helper); + + if (!g_spawn_sync (NULL, /* working directory */ + (gchar **) argv, + NULL, /* envp */ + 0, /* flags */ + NULL, /* child setup */ + NULL, /* user data */ + NULL, /* stdout */ + NULL, /* stderr */ + &exit_status, + &error)) + { + g_debug ("... %s", error->message); + goto out; + } + + if (exit_status != 0) + { + g_debug ("... wait status %d", exit_status); + goto out; + } + + g_debug ("... it works"); + ret = TRUE; +out: + g_free (helper); + g_clear_error (&error); + return ret; +} + gboolean srt_architecture_can_run_i386 (void) { - /* TODO */ -#if defined(__i386__) - return TRUE; -#else - return FALSE; -#endif + return _srt_architecture_can_run ("i386-linux-gnu"); } gboolean srt_architecture_can_run_x86_64 (void) { - /* TODO */ -#if defined(__x86_64__) && defined(__LP64__) - return TRUE; -#else - return FALSE; -#endif + return _srt_architecture_can_run ("x86_64-linux-gnu"); } diff --git a/steam-runtime-tools/meson.build b/steam-runtime-tools/meson.build index e278a3b76c8f9bea2530cc1557e1fe18d3fd1c77..3758fad9e7340a91e41b5397374b55ef087943ae 100644 --- a/steam-runtime-tools/meson.build +++ b/steam-runtime-tools/meson.build @@ -21,6 +21,8 @@ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +libdl = c_compiler.find_library('dl', required : false) + libsteamrt_sources = [ 'architecture.c', ] @@ -41,9 +43,13 @@ libsteamrt = library( c_args : [ '-DG_LOG_DOMAIN="' + meson.project_name() + '"', '-D_SRT_COMPILATION', + '-D_GNU_SOURCE', + '-D_SRT_SONAME="libsteam-runtime-tools-' + api_major + '.so.' + abi_major + '"', + '-D_SRT_MULTIARCH="' + multiarch + '"', + '-D_SRT_API_MAJOR="' + api_major + '"', ], include_directories : project_include_dirs, - dependencies : [glib, gobject], + dependencies : [glib, gobject, libdl], soversion : abi_major, version : abi_major + '.' + abi_minor, install : true, diff --git a/tests/meson.build b/tests/meson.build index 2e3cce267e191a27a1bc7a28457293d55563c71e..e60bc013986a9c376ac2fcca0171e7074684a364 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -24,6 +24,7 @@ test_env = environment() test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) +test_env.set('SRT_HELPERS_PATH', join_paths(meson.current_build_dir(), '..', 'helpers')) tests = [ 'architecture',