sudo apt update -y
sudo env DEBIAN_FRONTEND=noninteractive apt install -y \
doxygen libxcb-xkb-dev valgrind ninja-build \
- libwayland-dev wayland-protocols bison graphviz
+ libwayland-dev wayland-protocols bison graphviz ruby-ronn
- name: Setup
run: |
meson setup build
runs-on: macos-10.15
steps:
- uses: actions/checkout@v2
+ - uses: actions/setup-ruby@v1
- uses: actions/setup-python@v1
with:
python-version: '3.7'
- name: Install dependencies
run: |
python -m pip install --upgrade pip meson
+ gem install ronn
brew install doxygen bison ninja
brew link bison --force
env:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
+ - uses: actions/setup-ruby@v1
- uses: actions/setup-python@v1
with:
python-version: '3.7'
- name: Install dependencies
run: |
python -m pip install --upgrade pip meson
+ gem install ronn
choco install ninja winflexbison3 -y --no-progress --stop-on-first-failure
- name: Setup
shell: cmd
pkgconfig = import('pkgconfig')
cc = meson.get_compiler('c')
+dir_libexec = join_paths(get_option('prefix'), get_option('libexecdir'), 'xkbcommon')
+dir_man = join_paths(get_option('prefix'), get_option('mandir'))
# Compiler flags.
foreach cflag: [
# config.h.
configh_data = configuration_data()
+configh_data.set('EXIT_INVALID_USAGE', '2')
+configh_data.set_quoted('LIBXKBCOMMON_VERSION', meson.project_version())
+configh_data.set_quoted('LIBXKBCOMMON_TOOL_PATH', dir_libexec)
# Like AC_USE_SYSTEM_EXTENSIONS, what #define to use to get extensions
# beyond the base POSIX function set.
if host_machine.system() == 'sunos'
have_getopt = cc.has_header_symbol('getopt.h', 'getopt')
have_getopt_long = cc.has_header_symbol('getopt.h', 'getopt_long',
prefix: '#define _GNU_SOURCE')
+if have_getopt_long
+ configh_data.set10('HAVE_GETOPT_LONG', true)
+endif
# Silence some security & deprecation warnings on MSVC
# for some unix/C functions we use.
executable('fuzz-keymap', 'fuzz/keymap/target.c', dependencies: test_dep)
executable('fuzz-compose', 'fuzz/compose/target.c', dependencies: test_dep)
+man_pages = []
-# Demo programs.
+# Tools
build_tools = have_getopt
if build_tools
libxkbcommon_tools_internal = static_library(
link_with: libxkbcommon_tools_internal,
)
+ executable('xkbcli', 'tools/xkbcli.c',
+ dependencies: tools_dep, install: true)
+ man_pages += 'tools/xkbcli.1.ronn'
+
if have_getopt_long
executable('xkbcommon-rmlvo-to-keymap', 'tools/rmlvo-to-keymap.c', dependencies: tools_dep)
executable('xkbcommon-how-to-type', 'tools/how-to-type.c', dependencies: tools_dep)
endif
endif
+if get_option('enable-manpages')
+ prog_ronn = find_program('ronn', required: true)
+ foreach manpage : man_pages
+ # man page filenames adhere to directory/topic.section.ronn
+ topic = manpage.split('/')[-1].split('.')[-3]
+ section = manpage.split('.')[-2]
+ output = '@0@.@1@'.format(topic, section)
+ custom_target(output,
+ input: manpage,
+ output: output,
+ command: [prog_ronn, '--manual=libxkbcommon manual', '--pipe', '--roff', files(manpage)],
+ capture: true,
+ install: true,
+ install_dir: join_paths(dir_man, section))
+ endforeach
+endif
+
# xkeyboard-config "verifier"
xkct_config = configuration_data()
xkct_config.set('MESON_BUILD_ROOT', meson.build_root())
value: true,
description: 'Enable building libxkbregistry',
)
+option(
+ 'enable-manpages',
+ type: 'boolean',
+ value: true,
+ description: 'Enable building man pages',
+)
#include <limits.h>
#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _MSC_VER
#include <io.h>
#include <windows.h>
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
#else
#include <unistd.h>
#include <termios.h>
#endif
+#include "utils.h"
#include "tools-common.h"
void
(void) tcsetattr(STDIN_FILENO, TCSADRAIN, &termios);
}
}
+
#endif
+
+static inline bool
+tools_setup_path(void)
+{
+ const char *path = getenv("PATH");
+ const char *extra_path = LIBXKBCOMMON_TOOL_PATH;
+ char new_path[PATH_MAX];
+
+ if (snprintf_safe(new_path, sizeof(new_path), "%s:%s",
+ extra_path, path ? path : "")) {
+ setenv("PATH", new_path, 1);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int
+tools_exec_command(const char *prefix, int real_argc, char **real_argv)
+{
+ char *argv[64] = {NULL};
+ char executable[128];
+ const char *command;
+
+ assert((size_t)real_argc < ARRAY_SIZE(argv));
+
+ command = real_argv[0];
+
+ if (!snprintf_safe(executable, sizeof(executable),
+ "%s-%s", prefix, command)) {
+ fprintf(stderr, "Failed to assemble command\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!tools_setup_path()) {
+ fprintf(stderr, "Failed to set PATH\n");
+ return EXIT_FAILURE;
+ }
+
+ argv[0] = executable;
+ for (int i = 1; i < real_argc; i++)
+ argv[i] = real_argv[i];
+
+ execvp(executable, argv);
+ if (errno == ENOENT) {
+ fprintf(stderr, "Command '%s' is not available\n", command);
+ return EXIT_INVALID_USAGE;
+ } else {
+ fprintf(stderr, "Failed to execute '%s' (%s)\n",
+ command, strerror(errno));
+ }
+
+ return EXIT_FAILURE;
+}
void
tools_enable_stdin_echo(void);
+int
+tools_exec_command(const char *prefix, int argc, char **argv);
+
#ifdef _MSC_VER
#define setenv(varname, value, overwrite) _putenv_s((varname), (value))
#define unsetenv(varname) _putenv_s(varname, "")
--- /dev/null
+# xkbcli(1) - tool to interact with XKB keymaps
+
+## SYNOPSIS
+
+**xkbcli** [--help|--version] <command> [<args>]
+
+## DESCRIPTION
+
+**xkbcli** is a commandline tool to query, compile and test XKB keymaps,
+layouts and other elements.
+
+## OPTIONS
+
+ * `--help`:
+ Print help and exit
+
+ * `--version`:
+ Print the version and exit
+
+## EXIT STATUS
+
+ * 0:
+ exited successfully
+ * 1:
+ an error occured
+ * 2:
+ program was called with invalid arguments
+
+## SEE ALSO
+
+The libxkbcommon online documentation at <https://xkbcommon.org>
--- /dev/null
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * 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 (including the next
+ * paragraph) 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.
+ */
+
+#include "config.h"
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tools-common.h"
+
+static void
+usage(void)
+{
+ printf("Usage: xkbcli [--help|-h] [--version|-V] <command> [<args>]\n"
+ "\n"
+ "Global options:\n"
+ " -h, --help ...... show this help and exit\n"
+ " -V, --version ... show version information and exit\n"
+ "\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ enum options {
+ OPT_HELP = 1,
+ OPT_VERSION,
+ };
+ int option_index = 0;
+
+ while (1) {
+ int c;
+#if HAVE_GETOPT_LONG
+ static struct option opts[] = {
+ { "help", no_argument, 0, OPT_HELP },
+ { "version", no_argument, 0, OPT_VERSION },
+ { 0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "+hV", opts, &option_index);
+#else
+ c = getopt(argc, argv, "+hV");
+#endif
+ if (c == -1)
+ break;
+
+ switch(c) {
+ case 'h':
+ case OPT_HELP:
+ usage();
+ return EXIT_SUCCESS;
+ case 'V':
+ case OPT_VERSION:
+ printf("%s\n", LIBXKBCOMMON_VERSION);
+ return EXIT_SUCCESS;
+ default:
+ usage();
+ return EXIT_INVALID_USAGE;
+ }
+ }
+
+ if (optind >= argc) {
+ usage();
+ return EXIT_INVALID_USAGE;
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ return tools_exec_command("xkbcli", argc, argv);
+}