[pacman-dev] [PATCH] Add meson.build files to build with meson
Provide both build systems in parallel for now, to ensure that we work out all the differences between the two. Some time from now, we'll give up on autotools. Meson tends to be faster and probably easier to read/maintain. On my machine, the full meson configure+build+install takes a little under half as long as a similar autotools-based invocation. Building with meson is a two step process. First, configure the build: meson build Then, compile the project: ninja -C build There's some mild differences in functionality between meson and autotools. specifically: 1) No singular update-po target. meson only generates individual update-po targets for each textdomain (of which we have 3). To make this easier, there's a build-aux/update-po script which finds all update-po targets and runs them. 2) No doxygen support. Doxygen seems to be terrible and requires that everything be built through the Doxyfile. Support for out-of-tree builds (enforced by meson) appears to be nonexistant. I'd suggest just running doxygen directly since we never package these files and just export them for the website. 3) No 'make dist' equivalent. Just run 'git archive' to generate a suitable tarball for distribution. --- Yes, this is huge. All 330 tests pass, and I've been building/using pacman from my 'meson' branch for a while now. Feedback wanted. .ycm_extra_conf.py | 250 ++++++++++ build-aux/edit-script.sh.in | 33 ++ build-aux/meson-make-symlink.sh | 12 + build-aux/tap-driver.py | 296 +++++++++++ build-aux/update-po | 39 ++ doc/meson.build | 118 +++++ lib/libalpm/meson.build | 33 ++ lib/libalpm/po/meson.build | 15 + meson.build | 487 +++++++++++++++++++ meson_options.txt | 58 +++ scripts/libmakepkg/integrity/meson.build | 20 + scripts/libmakepkg/lint_config/meson.build | 18 + scripts/libmakepkg/lint_package/meson.build | 20 + scripts/libmakepkg/lint_pkgbuild/meson.build | 37 ++ scripts/libmakepkg/meson.build | 31 ++ scripts/libmakepkg/source/meson.build | 22 + scripts/libmakepkg/tidy/meson.build | 23 + scripts/libmakepkg/util/meson.build | 24 + scripts/meson.build | 66 +++ scripts/po/meson.build | 15 + src/common/meson.build | 4 + src/pacman/meson.build | 23 + src/pacman/po/meson.build | 15 + src/util/meson.build | 3 + test/pacman/meson.build | 357 ++++++++++++++ test/scripts/meson.build | 12 + test/util/meson.build | 6 + 27 files changed, 2037 insertions(+) create mode 100644 .ycm_extra_conf.py create mode 100644 build-aux/edit-script.sh.in create mode 100644 build-aux/meson-make-symlink.sh create mode 100644 build-aux/tap-driver.py create mode 100755 build-aux/update-po create mode 100644 doc/meson.build create mode 100644 lib/libalpm/meson.build create mode 100644 lib/libalpm/po/meson.build create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100644 scripts/libmakepkg/integrity/meson.build create mode 100644 scripts/libmakepkg/lint_config/meson.build create mode 100644 scripts/libmakepkg/lint_package/meson.build create mode 100644 scripts/libmakepkg/lint_pkgbuild/meson.build create mode 100644 scripts/libmakepkg/meson.build create mode 100644 scripts/libmakepkg/source/meson.build create mode 100644 scripts/libmakepkg/tidy/meson.build create mode 100644 scripts/libmakepkg/util/meson.build create mode 100644 scripts/meson.build create mode 100644 scripts/po/meson.build create mode 100644 src/common/meson.build create mode 100644 src/pacman/meson.build create mode 100644 src/pacman/po/meson.build create mode 100644 src/util/meson.build create mode 100644 test/pacman/meson.build create mode 100644 test/scripts/meson.build create mode 100644 test/util/meson.build diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 00000000..f297deef --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python + +# SPDX-License-Identifier: Unlicense +# +# Based on the template file provided by the 'YCM-Generator' project authored by +# Reuben D'Netto. +# Jiahui Xie has re-reformatted and expanded the original script in accordance +# to the requirements of the PEP 8 style guide and 'systemd' project, +# respectively. +# +# The original license is preserved as it is. +# +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# 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 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. +# +# For more information, please refer to <http://unlicense.org/> + +""" +YouCompleteMe configuration file tailored to support the 'meson' build system +used by the 'systemd' project. +""" + +import glob +import os +import ycm_core + + +SOURCE_EXTENSIONS = (".C", ".cpp", ".cxx", ".cc", ".c", ".m", ".mm") +HEADER_EXTENSIONS = (".H", ".h", ".hxx", ".hpp", ".hh") + + +def DirectoryOfThisScript(): + """ + Return the absolute path of the parent directory containing this + script. + """ + return os.path.dirname(os.path.abspath(__file__)) + + +def GuessBuildDirectory(): + """ + Guess the build directory using the following heuristics: + + 1. Returns the current directory of this script plus 'build' + subdirectory in absolute path if this subdirectory exists. + + 2. Otherwise, probes whether there exists any directory + containing '.ninja_log' file two levels above the current directory; + returns this single directory only if there is one candidate. + """ + result = os.path.join(DirectoryOfThisScript(), "build") + + if os.path.exists(result): + return result + + result = glob.glob(os.path.join(DirectoryOfThisScript(), + "..", "..", "*", ".ninja_log")) + + if not result: + return "" + + if 1 != len(result): + return "" + + return os.path.split(result[0])[0] + + +def TraverseByDepth(root, include_extensions): + """ + Return a set of child directories of the 'root' containing file + extensions specified in 'include_extensions'. + + NOTE: + 1. The 'root' directory itself is excluded from the result set. + 2. No subdirectories would be excluded if 'include_extensions' is left + to 'None'. + 3. Each entry in 'include_extensions' must begin with string '.'. + """ + is_root = True + result = set() + # Perform a depth first top down traverse of the given directory tree. + for root_dir, subdirs, file_list in os.walk(root): + if not is_root: + # print("Relative Root: ", root_dir) + # print(subdirs) + if include_extensions: + get_ext = os.path.splitext + subdir_extensions = { + get_ext(f)[-1] for f in file_list if get_ext(f)[-1] + } + if subdir_extensions & include_extensions: + result.add(root_dir) + else: + result.add(root_dir) + else: + is_root = False + + return result + + +_project_src_dir = os.path.join(DirectoryOfThisScript(), "src") +_include_dirs_set = TraverseByDepth(_project_src_dir, frozenset({".h"})) +flags = [ + "-x", + "c" + # The following flags are partially redundant due to the existence of + # 'compile_commands.json'. + # '-Wall', + # '-Wextra', + # '-Wfloat-equal', + # '-Wpointer-arith', + # '-Wshadow', + # '-std=gnu99', +] + +for include_dir in _include_dirs_set: + flags.append("-I" + include_dir) + +# Set this to the absolute path to the folder (NOT the file!) containing the +# compile_commands.json file to use that instead of 'flags'. See here for +# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html +# +# You can get CMake to generate this file for you by adding: +# set( CMAKE_EXPORT_COMPILE_COMMANDS 1 ) +# to your CMakeLists.txt file. +# +# Most projects will NOT need to set this to anything; you can just change the +# 'flags' list of compilation flags. Notice that YCM itself uses that approach. +compilation_database_folder = GuessBuildDirectory() + +if os.path.exists(compilation_database_folder): + database = ycm_core.CompilationDatabase(compilation_database_folder) +else: + database = None + + +def MakeRelativePathsInFlagsAbsolute(flags, working_directory): + """ + Iterate through 'flags' and replace the relative paths prefixed by + '-isystem', '-I', '-iquote', '--sysroot=' with absolute paths + start with 'working_directory'. + """ + if not working_directory: + return list(flags) + new_flags = [] + make_next_absolute = False + path_flags = ["-isystem", "-I", "-iquote", "--sysroot="] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith("/"): + new_flag = os.path.join(working_directory, flag) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith(path_flag): + path = flag[len(path_flag):] + new_flag = path_flag + os.path.join(working_directory, path) + break + + if new_flag: + new_flags.append(new_flag) + return new_flags + + +def IsHeaderFile(filename): + """ + Check whether 'filename' is considered as a header file. + """ + extension = os.path.splitext(filename)[1] + return extension in HEADER_EXTENSIONS + + +def GetCompilationInfoForFile(filename): + """ + Helper function to look up compilation info of 'filename' in the 'database'. + """ + # The compilation_commands.json file generated by CMake does not have + # entries for header files. So we do our best by asking the db for flags for + # a corresponding source file, if any. If one exists, the flags for that + # file should be good enough. + if not database: + return None + + if IsHeaderFile(filename): + basename = os.path.splitext(filename)[0] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists(replacement_file): + compilation_info = \ + database.GetCompilationInfoForFile(replacement_file) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile(filename) + + +def FlagsForFile(filename, **kwargs): + """ + Callback function to be invoked by YouCompleteMe in order to get the + information necessary to compile 'filename'. + + It returns a dictionary with a single element 'flags'. This element is a + list of compiler flags to pass to libclang for the file 'filename'. + """ + if database: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile(filename) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_) + + else: + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to) + + return { + "flags": final_flags, + "do_cache": True + } diff --git a/build-aux/edit-script.sh.in b/build-aux/edit-script.sh.in new file mode 100644 index 00000000..3e3a1b6a --- /dev/null +++ b/build-aux/edit-script.sh.in @@ -0,0 +1,33 @@ +#!@BASH@ + +input=$1 +output=$2 +mode=$3 + +"@SED@" \ + -e "s|@rootdir[@]|@ROOTDIR@|g" \ + -e "s|@localedir[@]|@LOCALEDIR@|g" \ + -e "s|@sysconfdir[@]|@sysconfdir@|g" \ + -e "s|@localstatedir[@]|@localstatedir@|g" \ + -e "s|@libmakepkgdir[@]|@LIBMAKEPKGDIR@|g" \ + -e "s|@pkgdatadir[@]|@PKGDATADIR@|g" \ + -e "s|@prefix[@]|@PREFIX@|g" \ + -e "1s|#!/bin/bash|#!@BASH@|g" \ + -e "s|@PACKAGE_VERSION[@]|@PACKAGE_VERSION@|g" \ + -e "s|@PACKAGE_NAME[@]|@PACKAGE_NAME@|g" \ + -e "s|@BUILDSCRIPT[@]|@BUILDSCRIPT@|g" \ + -e "s|@TEMPLATE_DIR[@]|@TEMPLATE_DIR@|g" \ + -e "s|@DEBUGSUFFIX[@]|@DEBUGSUFFIX@|g" \ + -e "s|@INODECMD[@]|@INODECMD@|g" \ + -e "s|@OWNERCMD[@]|@OWNERCMD@|g" \ + -e "s|@MODECMD[@]|@MODECMD@|g" \ + -e "s|@SEDINPLACEFLAGS[@]|@SEDINPLACEFLAGS@|g" \ + -e "s|@SEDPATH[@]|@SEDPATH@|g" \ + -e "s|@DUFLAGS[@]|@DUFLAGS@|g" \ + -e "s|@DUPATH[@]|@DUPATH@|g" \ + -e "s|@configure_input[@]|Generated from ${output##*/}.sh.in; do not edit by hand.|g" \ + "$input" >"$output" + +if [[ $mode ]]; then + chmod "$mode" "$output" +fi diff --git a/build-aux/meson-make-symlink.sh b/build-aux/meson-make-symlink.sh new file mode 100644 index 00000000..501cd43d --- /dev/null +++ b/build-aux/meson-make-symlink.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -eu + +# this is needed mostly because $DESTDIR is provided as a variable, +# and we need to create the target directory... + +mkdir -vp "$(dirname "${DESTDIR:-}$2")" +if [ "$(dirname $1)" = . ]; then + ln -vfs -T "$1" "${DESTDIR:-}$2" +else + ln -vfs -T --relative "${DESTDIR:-}$1" "${DESTDIR:-}$2" +fi diff --git a/build-aux/tap-driver.py b/build-aux/tap-driver.py new file mode 100644 index 00000000..c231caec --- /dev/null +++ b/build-aux/tap-driver.py @@ -0,0 +1,296 @@ +#!/usr/bin/env python3 +# Adapted from tappy copyright (c) 2016, Matt Layman +# MIT license +# https://github.com/python-tap/tappy + +import io +import re +import subprocess +import sys + + +class Directive(object): + """A representation of a result line directive.""" + + skip_pattern = re.compile( + r"""^SKIP\S* + (?P<whitespace>\s*) # Optional whitespace. + (?P<reason>.*) # Slurp up the rest.""", + re.IGNORECASE | re.VERBOSE) + todo_pattern = re.compile( + r"""^TODO\b # The directive name + (?P<whitespace>\s*) # Immediately following must be whitespace. + (?P<reason>.*) # Slurp up the rest.""", + re.IGNORECASE | re.VERBOSE) + + def __init__(self, text): + """Initialize the directive by parsing the text. + The text is assumed to be everything after a '#\s*' on a result line. + """ + self._text = text + self._skip = False + self._todo = False + self._reason = None + + match = self.skip_pattern.match(text) + if match: + self._skip = True + self._reason = match.group('reason') + + match = self.todo_pattern.match(text) + if match: + if match.group('whitespace'): + self._todo = True + else: + # Catch the case where the directive has no descriptive text. + if match.group('reason') == '': + self._todo = True + self._reason = match.group('reason') + + @property + def text(self): + """Get the entire text.""" + return self._text + + @property + def skip(self): + """Check if the directive is a SKIP type.""" + return self._skip + + @property + def todo(self): + """Check if the directive is a TODO type.""" + return self._todo + + @property + def reason(self): + """Get the reason for the directive.""" + return self._reason + + +class Parser(object): + """A parser for TAP files and lines.""" + + # ok and not ok share most of the same characteristics. + result_base = r""" + \s* # Optional whitespace. + (?P<number>\d*) # Optional test number. + \s* # Optional whitespace. + (?P<description>[^#]*) # Optional description before #. + \#? # Optional directive marker. + \s* # Optional whitespace. + (?P<directive>.*) # Optional directive text. + """ + ok = re.compile(r'^ok' + result_base, re.VERBOSE) + not_ok = re.compile(r'^not\ ok' + result_base, re.VERBOSE) + plan = re.compile(r""" + ^1..(?P<expected>\d+) # Match the plan details. + [^#]* # Consume any non-hash character to confirm only + # directives appear with the plan details. + \#? # Optional directive marker. + \s* # Optional whitespace. + (?P<directive>.*) # Optional directive text. + """, re.VERBOSE) + diagnostic = re.compile(r'^#') + bail = re.compile(r""" + ^Bail\ out! + \s* # Optional whitespace. + (?P<reason>.*) # Optional reason. + """, re.VERBOSE) + version = re.compile(r'^TAP version (?P<version>\d+)$') + + TAP_MINIMUM_DECLARED_VERSION = 13 + + def parse(self, fh): + """Generate tap.line.Line objects, given a file-like object `fh`. + `fh` may be any object that implements both the iterator and + context management protocol (i.e. it can be used in both a + "with" statement and a "for...in" statement.) + Trailing whitespace and newline characters will be automatically + stripped from the input lines. + """ + with fh: + for line in fh: + yield self.parse_line(line.rstrip()) + + def parse_line(self, text): + """Parse a line into whatever TAP category it belongs.""" + match = self.ok.match(text) + if match: + return self._parse_result(True, match) + + match = self.not_ok.match(text) + if match: + return self._parse_result(False, match) + + if self.diagnostic.match(text): + return ('diagnostic', text) + + match = self.plan.match(text) + if match: + return self._parse_plan(match) + + match = self.bail.match(text) + if match: + return ('bail', match.group('reason')) + + match = self.version.match(text) + if match: + return self._parse_version(match) + + return ('unknown',) + + def _parse_plan(self, match): + """Parse a matching plan line.""" + expected_tests = int(match.group('expected')) + directive = Directive(match.group('directive')) + + # Only SKIP directives are allowed in the plan. + if directive.text and not directive.skip: + return ('unknown',) + + return ('plan', expected_tests, directive) + + def _parse_result(self, ok, match): + """Parse a matching result line into a result instance.""" + return ('result', ok, match.group('number'), + match.group('description').strip(), + Directive(match.group('directive'))) + + def _parse_version(self, match): + version = int(match.group('version')) + if version < self.TAP_MINIMUM_DECLARED_VERSION: + raise ValueError('It is an error to explicitly specify ' + 'any version lower than 13.') + return ('version', version) + + +class Rules(object): + + def __init__(self): + self._lines_seen = {'plan': [], 'test': 0, 'failed': 0, 'version': []} + self._errors = [] + + def check(self, final_line_count): + """Check the status of all provided data and update the suite.""" + if self._lines_seen['version']: + self._process_version_lines() + self._process_plan_lines(final_line_count) + + def check_errors(self): + if self._lines_seen['failed'] > 0: + self._add_error('Tests failed.') + if self._errors: + for error in self._errors: + print(error) + return 1 + return 0 + + def _process_version_lines(self): + """Process version line rules.""" + if len(self._lines_seen['version']) > 1: + self._add_error('Multiple version lines appeared.') + elif self._lines_seen['version'][0] != 1: + self._add_error('The version must be on the first line.') + + def _process_plan_lines(self, final_line_count): + """Process plan line rules.""" + if not self._lines_seen['plan']: + self._add_error('Missing a plan.') + return + + if len(self._lines_seen['plan']) > 1: + self._add_error('Only one plan line is permitted per file.') + return + + expected_tests, at_line = self._lines_seen['plan'][0] + if not self._plan_on_valid_line(at_line, final_line_count): + self._add_error( + 'A plan must appear at the beginning or end of the file.') + return + + if expected_tests != self._lines_seen['test']: + self._add_error( + 'Expected {expected_count} tests ' + 'but only {seen_count} ran.'.format( + expected_count=expected_tests, + seen_count=self._lines_seen['test'])) + + def _plan_on_valid_line(self, at_line, final_line_count): + """Check if a plan is on a valid line.""" + # Put the common cases first. + if at_line == 1 or at_line == final_line_count: + return True + + # The plan may only appear on line 2 if the version is at line 1. + after_version = ( + self._lines_seen['version'] and + self._lines_seen['version'][0] == 1 and + at_line == 2) + if after_version: + return True + + return False + + def handle_bail(self, reason): + """Handle a bail line.""" + self._add_error('Bailed: {reason}').format(reason=reason) + + def handle_skipping_plan(self): + """Handle a plan that contains a SKIP directive.""" + sys.exit(77) + + def saw_plan(self, expected_tests, at_line): + """Record when a plan line was seen.""" + self._lines_seen['plan'].append((expected_tests, at_line)) + + def saw_test(self, ok): + """Record when a test line was seen.""" + self._lines_seen['test'] += 1 + if not ok: + self._lines_seen['failed'] += 1 + + def saw_version_at(self, line_counter): + """Record when a version line was seen.""" + self._lines_seen['version'].append(line_counter) + + def _add_error(self, message): + self._errors += [message] + + +if __name__ == '__main__': + parser = Parser() + rules = Rules() + + try: + out = subprocess.check_output(sys.argv[1:], universal_newlines=True) + except subprocess.CalledProcessError as e: + sys.stdout.write(e.output) + raise e + + line_generator = parser.parse(io.StringIO(out)) + line_counter = 0 + for line in line_generator: + line_counter += 1 + + if line[0] == 'unknown': + continue + + if line[0] == 'result': + rules.saw_test(line[1]) + print('{okay} {num} {description} {directive}'.format( + okay=('' if line[1] else 'not ') + 'ok', num=line[2], + description=line[3], directive=line[4].text)) + elif line[0] == 'plan': + if line[2].skip: + rules.handle_skipping_plan() + rules.saw_plan(line[1], line_counter) + elif line[0] == 'bail': + rules.handle_bail(line[1]) + elif line[0] == 'version': + rules.saw_version_at(line_counter) + elif line[0] == 'diagnostic': + print(line[1]) + + rules.check(line_counter) + sys.exit(rules.check_errors()) diff --git a/build-aux/update-po b/build-aux/update-po new file mode 100755 index 00000000..ce1ad4be --- /dev/null +++ b/build-aux/update-po @@ -0,0 +1,39 @@ +#!/bin/bash + +find_build_directory() { + local build_dirs=(*/.ninja_log) + + if [[ ! -e ${build_dirs[0]} ]]; then + echo "error: No build directory found. Have you run 'meson build' yet?" >&2 + return 1 + elif (( ${#build_dirs[*]} > 1 )); then + echo "error: Multiple build directories found. Unable to proceed." >&2 + return 1 + fi + + printf '%s\n' "${build_dirs[0]%/*}" +} + + +filter_targets_by_name() { + if command -v jq &>/dev/null; then + jq --arg re "$1" -r 'map(.name)[] | select(match($re))' + else + json_pp | awk -v filter="$1" -F'[:"]' \ + '$2 == "name" && $(NF - 1) ~ filter { print $(NF - 1) }' + fi +} + +# Make things simple and require that we're in the build root rather than +# trying to chase down the location of this script and the relative build dir. +if [[ ! -d .git ]]; then + echo "This script must be run from the root of the repository" >&2 + exit 1 +fi + +build_dir=$(find_build_directory) || exit 1 + +mapfile -t targets < \ + <(meson introspect "$build_dir" --targets | filter_targets_by_name "-update-po$") + +ninja -C "$build_dir" "${targets[@]}" diff --git a/doc/meson.build b/doc/meson.build new file mode 100644 index 00000000..b1ffd793 --- /dev/null +++ b/doc/meson.build @@ -0,0 +1,118 @@ +manpages = [ + { 'name': 'alpm-hooks.5' }, + { 'name': 'pacman.8' }, + { 'name': 'makepkg.8' }, + { 'name': 'makepkg-template.1' }, + { 'name': 'repo-add.8' }, + { 'name': 'vercmp.8' }, + { 'name': 'pkgdelta.8' }, + { 'name': 'pacman-key.8' }, + { 'name': 'PKGBUILD.5', 'extra_depends' : [ 'PKGBUILD-example.txt' ] }, + { 'name': 'makepkg.conf.5' }, + { 'name': 'pacman.conf.5' }, + { 'name': 'libalpm.3' }, + { 'name': 'BUILDINFO.5' }, +] + +asciidoc_conf = join_paths(meson.current_source_dir(), 'asciidoc.conf') + +asciidoc_opts = [ + '-f', asciidoc_conf, + '-a', 'pacman_version="@0@"'.format(PACKAGE_VERSION), + '-a', 'pacman_date=@0@'.format(run_command('date', '+%Y-%m-%d').stdout().strip()), + '-a', 'pkgdatadir=@0@'.format(PKGDATADIR), + '-a', 'localstatedir=@0@'.format(LOCALSTATEDIR), + '-a', 'sysconfdir=@0@'.format(SYSCONFDIR), + '-a', 'datarootdir=@0@'.format(DATAROOTDIR), +] + +html_targets = [] +html_files = [] + +foreach page : manpages + manpage = page['name'] + htmlpage = '@0@.html'.format(manpage) + input = '@0@.asciidoc'.format(manpage) + + section = page['name'].split('.')[-1] + + mandirn = join_paths(MANDIR, 'man' + section) + + custom_target( + manpage, + command : [ + A2X, + '--no-xmllint', + '-d', 'manpage', + '-f', 'manpage', + '--xsltproc-opts', '-param man.endnotes.list.enabled 0 -param man.endnotes.are.numbered 0', + '-D', '@OUTDIR@', + '--asciidoc-opts', ' '.join(asciidoc_opts), + '@INPUT@', + ], + input : input, + output : [manpage], + depend_files : [ + asciidoc_conf, + ] + page.get('extra_depends', []), + install : true, + install_dir : mandirn, + ) + + html = custom_target( + htmlpage, + command : [ + ASCIIDOC, + ] + asciidoc_opts + [ + '-a', 'linkcss', + '-a', 'toc', + '-a', 'icons', + '-a', 'max-width=960px', + '-a', 'stylesheet=asciidoc-override.css', + '-o', '@OUTPUT@', + '@INPUT@', + ], + input : input, + output : [htmlpage], + depend_files : [ + asciidoc_conf, + 'asciidoc-override.css', + ] + page.get('extra_depends', []), + build_by_default : false, + install : false, + ) + html_targets += [html] + html_files += [htmlpage] +endforeach + +run_target('html', + command : ['/bin/true'], + depends : html_targets) + +custom_target( + 'website.tar.gz', + command : [ + 'bsdtar', 'czf', '@OUTPUT@', + '-C', meson.current_build_dir(), + ] + html_files + [ + '-C', meson.current_source_dir(), + 'submitting-patches.html', + 'translation-help.html', + 'HACKING.html', + 'index.html', + 'asciidoc-override.css', + '-C', '/etc/asciidoc/stylesheets/', + 'asciidoc.css', + '-C', '/etc/asciidoc/javascripts/', + 'asciidoc.js', + '-C', '/etc/asciidoc/', + 'images', + ], + output : ['website.tar.gz'], + build_by_default : false, + depends : html_targets, +) + +meson.add_install_script(MESON_MAKE_SYMLINK, + 'repo-add.8', + join_paths(MANDIR, 'man8/repo-remove.8')) diff --git a/lib/libalpm/meson.build b/lib/libalpm/meson.build new file mode 100644 index 00000000..84c3dde3 --- /dev/null +++ b/lib/libalpm/meson.build @@ -0,0 +1,33 @@ +libalpm_sources = files(''' + add.h add.c + alpm.h alpm.c + alpm_list.h alpm_list.c + backup.h backup.c + base64.h base64.c + be_local.c + be_package.c + be_sync.c + conflict.h conflict.c + db.h db.c + delta.h delta.c + deps.h deps.c + diskspace.h diskspace.c + dload.h dload.c + error.c + filelist.h filelist.c + graph.h graph.c + group.h group.c + handle.h handle.c + hook.h hook.c + libarchive-compat.h + log.h log.c + package.h package.c + pkghash.h pkghash.c + rawstr.c + remove.h remove.c + signing.c signing.h + sync.h sync.c + trans.h trans.c + util.h util.c + version.c +'''.split()) diff --git a/lib/libalpm/po/meson.build b/lib/libalpm/po/meson.build new file mode 100644 index 00000000..cec28a15 --- /dev/null +++ b/lib/libalpm/po/meson.build @@ -0,0 +1,15 @@ +i18n.gettext( + 'libalpm', + args : [ + '--directory=@0@'.format(meson.current_source_dir()), + '--msgid-bugs-address=http://bugs.archlinux.org/index.php?project=3', + '--copyright-holder="Pacman Development Team <pacman-dev@archlinux.org>"', + '--language', 'c', + + '--keyword=_', + '--flag=_:1:c-format', + + '--keyword=_n:1,2', + '--flag=_n:1:c-format', + '--flag=_n:2:c-format', + ]) diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..3f9b2ae0 --- /dev/null +++ b/meson.build @@ -0,0 +1,487 @@ +project('pacman', + 'c', + version : '5.1.0', + license : 'GPLv2+', + default_options : [ + 'c_std=gnu99', + 'prefix=/usr', + 'sysconfdir=/etc', + 'localstatedir=/var', + ], + meson_version : '>= 0.47') + +libalpm_version = '11.0.1' + +cc = meson.get_compiler('c') + +# commandline options +PREFIX = get_option('prefix') +DATAROOTDIR = join_paths(PREFIX, get_option('datarootdir')) +SYSCONFDIR = join_paths(PREFIX, get_option('sysconfdir')) +LOCALSTATEDIR = join_paths(PREFIX, get_option('localstatedir')) +LOCALEDIR = join_paths(PREFIX, get_option('localedir')) +ROOTDIR = get_option('root-dir') +BINDIR = join_paths(PREFIX, get_option('bindir')) +MANDIR = join_paths(PREFIX, get_option('mandir')) +BUILDSCRIPT = get_option('buildscript') +LIBMAKEPKGDIR = join_paths(PREFIX, DATAROOTDIR, 'makepkg') +PKGDATADIR = join_paths(PREFIX, DATAROOTDIR, meson.project_name()) + +PYTHON = find_program('python') +M4 = find_program('m4') +SED = find_program('sed') +DU = find_program('du') +LDCONFIG = get_option('ldconfig') +MESON_MAKE_SYMLINK = join_paths(meson.source_root(), 'build-aux/meson-make-symlink.sh') + +BASH = find_program('bash4', 'bash') +if BASH.found() + bash_version = run_command(BASH, '-c', 'IFS=.; echo "${BASH_VERSINFO[*]:0:3}"').stdout() + + have_bash = bash_version.version_compare('>= 4.4.0') +endif +if not have_bash + error('bash >= 4.4.0 is required for pacman scripts.') +endif + +bashcompletion = dependency('bash-completion', required : false) +if bashcompletion.found() + BASHCOMPDIR = bashcompletion.get_pkgconfig_variable('completionsdir') +else + BASHCOMPDIR = join_paths(DATAROOTDIR, 'bash-completion/completions') +endif + +if get_option('use-git-version') + PACKAGE_VERSION = run_command( + find_program('git'), + 'describe', + '--abbrev=4', + '--dirty').stdout().strip().strip('v') +else + PACKAGE_VERSION = meson.project_version() +endif + +conf = configuration_data() +conf.set('_GNU_SOURCE', true) +conf.set_quoted('PACKAGE', meson.project_name()) +conf.set_quoted('PACKAGE_VERSION', PACKAGE_VERSION) +conf.set_quoted('LOCALEDIR', LOCALEDIR) +conf.set_quoted('SCRIPTLET_SHELL', get_option('scriptlet-shell')) +conf.set_quoted('LDCONFIG', LDCONFIG) +conf.set_quoted('LIB_VERSION', meson.project_version()) +conf.set_quoted('SYSHOOKDIR', join_paths(DATAROOTDIR, 'libalpm/hooks/')) +conf.set_quoted('CONFFILE', join_paths(SYSCONFDIR, 'pacman.conf')) +conf.set_quoted('DBPATH', join_paths(LOCALSTATEDIR, 'lib/pacman')) +conf.set_quoted('GPGDIR', join_paths(SYSCONFDIR, 'pacman.d/gnupg')) +conf.set_quoted('LOGFILE', join_paths(LOCALSTATEDIR, 'log/pacman.log')) +conf.set_quoted('CACHEDIR', join_paths(LOCALSTATEDIR, 'cache/pacman/pkg')) +conf.set_quoted('HOOKDIR', join_paths(SYSCONFDIR, 'pacman.d/hooks/')) +conf.set_quoted('ROOTDIR', ROOTDIR) + +if get_option('i18n') + if not cc.has_function('ngettext') + error('ngettext not found but NLS support requested') + endif + conf.set('ENABLE_NLS', 1) +endif + +# dependencies +libarchive = dependency('libarchive', + version : '>=3.0.0', + static : get_option('buildstatic')) + +libcurl = dependency('libcurl', + version : '>=7.32.0', + required : get_option('curl'), + static : get_option('buildstatic')) +conf.set('HAVE_LIBCURL', libcurl.found()) + +want_gpgme = get_option('gpgme') +gpgme_config = find_program('gpgme-config', required : want_gpgme) +if not want_gpgme.disabled() and gpgme_config.found() + gpgme_version = run_command(gpgme_config, '--version').stdout().strip() + + needed_gpgme_version = '>=1.3.0' + have = gpgme_version.version_compare(needed_gpgme_version) + if want_gpgme.enabled() and not have + error('gpgme @0@ is needed for GPG signature support'.format(needed_gpgme_version)) + endif + + gpgme_libs = [ + cc.find_library('gpgme', required : have, + dirs : [get_option('gpgme-libdir')]), + cc.find_library('gpg-error', required : have, + dirs : [get_option('gpgme-libdir')]), + cc.find_library('assuan', required : have, + dirs : [get_option('gpgme-libdir')]), + ] + + conf.set('HAVE_LIBGPGME', have) +else + gpgme_libs = [] + conf.set('HAVE_LIBGPGME', false) +endif + +want_crypto = get_option('crypto') +if want_crypto == 'openssl' + libcrypto = dependency('libcrypto', static : get_option('buildstatic')) + if not libcrypto.found() + error('openssl support requested but not found') + endif + crypto_provider = libcrypto + conf.set10('HAVE_LIBSSL', true) +elif want_crypto == 'nettle' + libnettle = dependency('nettle', static : get_option('buildstatic')) + if not libnettle.found() + error('nettle support requested but not found') + endif + crypto_provider = libnettle + conf.set10('HAVE_LIBNETTLE', true) +else + error('unhandled crypto value @0@'.format(want_crypto)) +endif + +foreach header : [ + 'mntent.h', + 'sys/mnttab.h', + 'sys/mount.h', + 'sys/param.h', + 'sys/statvfs.h', + 'sys/types.h', + 'sys/ucred.h', + 'termios.h', + ] + if cc.has_header(header) + conf.set('HAVE_' + header.underscorify().to_upper(), true) + endif +endforeach + +foreach sym : [ + 'dup2', + 'fork', + 'getcwd', + 'getmntent', + 'getmntinfo', + 'gettimeofday', + 'memmove', + 'memset', + 'mkdir', + 'realpath', + 'regcomp', + 'rmdir', + 'setenv', + 'setlocale', + 'strcasecmp', + 'strchr', + 'strcspn', + 'strdup', + 'strerror', + 'strndup', + 'strnlen', + 'strnlen', + 'strrchr', + 'strsep', + 'strsep', + 'strstr', + 'strtol', + 'swprintf', + 'tcflush', + 'tcflush', + 'uname', + 'wcwidth', + ] + have = cc.has_function(sym, args : '-D_GNU_SOURCE') + conf.set10('HAVE_' + sym.to_upper(), have) +endforeach + +foreach member : [ + ['struct stat', 'st_blksize', '''#include <sys/stat.h>'''], + ['struct statvfs', 'f_flag', '''#include <sys/statvfs.h>'''], + ['struct statfs', 'f_flags', '''#include <sys/param.h> + #include <sys/mount.h>'''], + ] + have = cc.has_member(member[0], member[1], prefix : member[2]) + conf.set('HAVE_' + '_'.join([member[0], member[1]]).underscorify().to_upper(), have) +endforeach + +if conf.has('HAVE_STRUCT_STATVFS_F_FLAG') + conf.set('FSSTATSTYPE', 'struct statvfs') +elif conf.has('HAVE_STRUCT_STATFS_F_FLAGS') + conf.set('FSSTATSTYPE', 'struct statfs') +endif + +if get_option('buildtype') == 'debug' + extra_cflags = [ + '-Wcast-align', + '-Wclobbered', + '-Wempty-body', + '-Wfloat-equal', + '-Wformat-nonliteral', + '-Wformat-security', + '-Wignored-qualifiers', + '-Winit-self', + '-Wlogical-op', + '-Wmissing-declarations', + '-Wmissing-field-initializers', + '-Wmissing-parameter-type', + '-Wmissing-prototypes', + '-Wold-style-declaration', + '-Woverride-init', + '-Wpointer-arith', + '-Wredundant-decls', + '-Wshadow', + '-Wsign-compare', + '-Wstrict-aliasing', + '-Wstrict-overflow=5', + '-Wstrict-prototypes', + '-Wtype-limits', + '-Wuninitialized', + '-Wunused-but-set-parameter', + '-Wunused-parameter', + '-Wwrite-strings', + ] + add_project_arguments(cc.get_supported_arguments(extra_cflags), language : 'c') + + conf.set('PACMAN_DEBUG', 1) +endif + +config_h = configure_file( + output : 'config.h', + configuration : conf) +add_project_arguments('-include', 'config.h', language : 'c') + +default_duflags = ' -sk --apparent-size' +default_sedinplaceflags = ' --follow-symlinks -i' +inodecmd = 'stat -c \'%i %n\'' +ownercmd = 'stat -c \'%u:%g\'' +modecmd = 'stat -c \'%a\'' +strip_binaries = '--strip-all' +strip_shared = '--strip-unneeded' +strip_static = '--strip-debug' + +os = host_machine.system() +if os.startswith('darwin') + inodecmd = '/usr/bin/stat -f \'%i %n\'' + ownercmd = '/usr/bin/stat -f \'%u:%g\'' + modecmd = '/usr/bin/stat -f \'%lp\'' + default_sedinplaceflags = ' -i \'\'' + default_duflags = ' -sk' + strip_binaries = '' + strip_shared = '-s' + strip_static = '-s' +elif os.contains('bsd') or os == 'dragonfly' + inodecmd = 'stat -f \'%i %n\'' + ownercmd = 'stat -f \'%u:%g\'' + modecmd = 'stat -f \'%lp\'' + default_sedinplaceflags = ' -i \'\'' + default_duflags = ' -sk' +endif + +duflags = get_option('duflags') +if duflags == 'autodetect' + duflags = default_duflags +endif + +sedinplaceflags = get_option('sedinplaceflags') +if sedinplaceflags == 'auto' + sedinplaceflags = default_sedinplaceflags +endif + +chost = run_command(cc, '-dumpmachine').stdout().strip() +carch = chost.split('-')[0] + +# annoyingly, we have to maintain two sets of configuration_data which is +# largely identical, but which distinguishes between quoting needs. +substs = configuration_data() +substs.set('SED', SED.path()) +substs.set('M4', M4.path()) +substs.set('CARCH', carch) +substs.set('CHOST', chost) +substs.set('PKGEXT', get_option('pkg-ext')) +substs.set('SRCEXT', get_option('src-ext')) +substs.set('ROOTDIR', ROOTDIR) +substs.set('LOCALEDIR', LOCALEDIR) +substs.set('sysconfdir', SYSCONFDIR) +substs.set('localstatedir', LOCALSTATEDIR) +substs.set('PKGDATADIR', PKGDATADIR) +substs.set('PREFIX', PREFIX) +substs.set('BASH', BASH.path()) +substs.set('PACKAGE_VERSION', PACKAGE_VERSION) +substs.set('PACKAGE_NAME', meson.project_name()) +substs.set('BUILDSCRIPT', BUILDSCRIPT) +substs.set('TEMPLATE_DIR', get_option('makepkg-template-dir')) +substs.set('DEBUGSUFFIX', get_option('debug-suffix')) +substs.set('INODECMD', inodecmd) +substs.set('OWNERCMD', ownercmd) +substs.set('MODECMD', modecmd) +substs.set('SEDINPLACEFLAGS', sedinplaceflags) +substs.set('SEDPATH', SED.path()) +substs.set('DUFLAGS', duflags) +substs.set('DUPATH', DU.path()) +substs.set('LIBMAKEPKGDIR', LIBMAKEPKGDIR) +substs.set('STRIP_BINARIES', strip_binaries) +substs.set('STRIP_SHARED', strip_shared) +substs.set('STRIP_STATIC', strip_static) + +subdir('lib/libalpm') +subdir('src/common') +subdir('src/pacman') +subdir('src/util') +subdir('scripts') + +# Internationalization +if get_option('i18n') + i18n = import('i18n') + subdir('lib/libalpm/po') + subdir('src/pacman/po') + subdir('scripts/po') +endif + +want_doc = get_option('doc') +ASCIIDOC = find_program('asciidoc', required : want_doc) +A2X = find_program('a2x', required : want_doc) +build_doc = A2X.found() and not want_doc.disabled() +if build_doc + subdir('doc') +endif + +libcommon = static_library( + 'common', + libcommon_sources, + install : false) + +includes = include_directories('src/common', 'lib/libalpm') + +libalpm = library( + 'alpm', + libalpm_sources, + version : libalpm_version, + include_directories : includes, + dependencies : [crypto_provider, libarchive, libcurl] + gpgme_libs, + link_with : [libcommon], + install : true) + +install_headers( + 'lib/libalpm/alpm.h', + 'lib/libalpm/alpm_list.h') + +# TODO: this is lacking libs.private +pkgconfig = import('pkgconfig') +pkgconfig.generate( + libalpm, + name : 'libalpm', + description : 'Arch Linux package management library', + version : libalpm_version, + url : 'http://www.archlinux.org/pacman/', + requires_private : [crypto_provider, libcurl, libarchive]) + +pacman_bin = executable( + 'pacman', + pacman_sources, + include_directories : includes, + link_with : [libalpm, libcommon], + dependencies : [libarchive], + install : true, +) + +executable( + 'pacman-conf', + pacman_conf_sources, + include_directories : includes, + link_with : [libalpm], + install : true, +) + +executable( + 'cleanupdelta', + cleanupdelta_sources, + include_directories : includes, + link_with : [libalpm], + install : true, +) + +executable( + 'testpkg', + testpkg_sources, + include_directories : includes, + link_with : [libalpm], + install : true, +) + +executable( + 'vercmp', + vercmp_sources, + include_directories : includes, + link_with : [libalpm], + install : true, +) + +configure_file( + input : 'etc/makepkg.conf.in', + output : 'makepkg.conf', + configuration : substs, + install_dir : SYSCONFDIR) + +configure_file( + input : 'etc/pacman.conf.in', + output : 'pacman.conf', + configuration : substs, + install_dir : SYSCONFDIR) + +install_data( + 'proto/PKGBUILD-split.proto', + 'proto/PKGBUILD-vcs.proto', + 'proto/PKGBUILD.proto', + 'proto/proto.install', + install_dir : join_paths(DATAROOTDIR, 'pacman')) + +TEST_ENV = environment() +TEST_ENV.set('PMTEST_SCRIPTLIB_DIR', join_paths(meson.source_root(), 'scripts/library/')) +TEST_ENV.set('PMTEST_LIBMAKEPKG_DIR', join_paths(meson.build_root(), 'scripts/libmakepkg/')) +TEST_ENV.set('PMTEST_UTIL_DIR', meson.build_root() + '/') +TEST_ENV.set('PMTEST_SCRIPT_DIR', join_paths(meson.build_root(), 'scripts/')) + +subdir('test/pacman') +subdir('test/scripts') +subdir('test/util') + +message('\n '.join([ + '@0@ @1@'.format(meson.project_name(), meson.project_version()), + 'Build information:', + ' prefix : @0@'.format(PREFIX), + ' sysconfdir : @0@'.format(SYSCONFDIR), + ' conf file : @0@'.format(join_paths(SYSCONFDIR, 'pacman.conf')), + ' localstatedir : @0@'.format(LOCALSTATEDIR), + ' database dir : @0@'.format(join_paths(LOCALSTATEDIR, 'lib/pacman/')), + ' cache dir : @0@'.format(join_paths(LOCALSTATEDIR, 'cache/pacman/pkg/')), + ' compiler : @0@ @1@'.format(cc.get_id(), cc.version()), + '', + ' Architecture : @0@'.format(carch), + ' Host Type : @0@'.format(chost), + ' File inode command : @0@'.format(inodecmd), + ' File owner command : @0@'.format(ownercmd), + ' File mode command : @0@'.format(modecmd), + ' Directory size command : @0@ @1@'.format(DU.path(), duflags), + ' In-place sed command : @0@ @1@'.format(SED.path(), sedinplaceflags), + ' libalpm version : @0@'.format(libalpm_version), + ' pacman version : @0@'.format(PACKAGE_VERSION), + '', + 'Directory and file information:', + ' root working directory : @0@'.format(ROOTDIR), + ' package extension : @0@'.format(get_option('pkg-ext')), + ' source pkg extension : @0@'.format(get_option('src-ext')), + ' build script name : @0@'.format(BUILDSCRIPT), + ' template directory : @0@'.format(get_option('makepkg-template-dir')), + '', + 'Compilation options:', + ' i18n support : @0@'.format(get_option('i18n')), + ' Build docs : @0@'.format(build_doc), + ' debug build : @0@'.format(get_option('buildtype') == 'debug'), + ' Use libcurl : @0@'.format(conf.get('HAVE_LIBCURL')), + ' Use GPGME : @0@'.format(conf.get('HAVE_LIBGPGME')), + ' Use OpenSSL : @0@'.format(conf.has('HAVE_LIBSSL') and + conf.get('HAVE_LIBSSL') == 1), + ' Use nettle : @0@'.format(conf.has('HAVE_LIBNETTLE') and + conf.get('HAVE_LIBNETTLE') == 1), + '', +])) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..9e6e527e --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,58 @@ +# build behavior +option('use-git-version', type : 'boolean', value : false, + description : 'take version information from git') +option('buildstatic', type : 'boolean', value : false, + description : 'if true, build staticly linked binaries') + +# directories and filenames +option('root-dir', type : 'string', value : '/', + description : 'set the location of the root operating directory') + +option('pkg-ext', type : 'string', value : '.pkg.tar.gz', + description : 'set the file extension used by packages') + +option('src-ext', type : 'string', value : '.src.tar.gz', + description : 'set the file extension used by source packages') + +option('scriptlet-shell', type : 'string', value : '/bin/sh', + description : 'The full path of the shell used to run install scriptlets') + +option('ldconfig', type : 'string', value : '/sbin/ldconfig', + description : 'set the full path to ldconfig') + +option('buildscript', type : 'string', value : 'PKGBUILD', + description : 'set the build script name used by makepkg') + +option('datarootdir', type : 'string', value : 'share', + description : 'FIXME') + +option('makepkg-template-dir', type : 'string', value : '/usr/share/makepkg-template', + description : 'template dir used by makepkg-template') + +option('debug-suffix', type : 'string', value : 'debug', + description : 'suffix for split debugging symbol packages used by makepkg') + +# dependencies, features +option('doc', type : 'feature', value : 'auto', + description : 'generate docs and manpages') + +option('curl', type : 'feature', value : 'auto', + description : 'use curl to download files') + +option('crypto', type : 'combo', choices : ['openssl', 'nettle'], + description : 'select crypto implementation') + +option('gpgme', type : 'feature', value : 'auto', + description : 'use GPGME for PGP signature verification') +option('gpgme-libdir', type : 'string', value : '/usr/lib', + description : 'search directory for gpgme libraries.') + +option('i18n', type : 'boolean', value : true, + description : 'enable localization of pacman, libalpm and scripts') + +# tools +option('duflags', type : 'string', value : 'autodetect', + description : 'flags to pass to du to measure file size') + +option('sedinplaceflags', type : 'string', value : 'auto', + description : 'flags to pass to sed to edit a file in-place') diff --git a/scripts/libmakepkg/integrity/meson.build b/scripts/libmakepkg/integrity/meson.build new file mode 100644 index 00000000..9aa9061c --- /dev/null +++ b/scripts/libmakepkg/integrity/meson.build @@ -0,0 +1,20 @@ +libmakepkg_module = 'integrity' + +sources = [ + 'generate_checksum.sh.in', + 'generate_signature.sh.in', + 'verify_checksum.sh.in', + 'verify_signature.sh.in', +] + +foreach src : sources + output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module) + + custom_target( + libmakepkg_module + '_' + src.underscorify(), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : src, + output : '@BASENAME@', + install : true, + install_dir : output_dir) +endforeach diff --git a/scripts/libmakepkg/lint_config/meson.build b/scripts/libmakepkg/lint_config/meson.build new file mode 100644 index 00000000..884d63d7 --- /dev/null +++ b/scripts/libmakepkg/lint_config/meson.build @@ -0,0 +1,18 @@ +libmakepkg_module = 'lint_config' + +sources = [ + 'paths.sh.in', + 'variable.sh.in', +] + +foreach src : sources + output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module) + + custom_target( + libmakepkg_module + '_' + src.underscorify(), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : src, + output : '@BASENAME@', + install : true, + install_dir : output_dir) +endforeach diff --git a/scripts/libmakepkg/lint_package/meson.build b/scripts/libmakepkg/lint_package/meson.build new file mode 100644 index 00000000..8eb1aaf7 --- /dev/null +++ b/scripts/libmakepkg/lint_package/meson.build @@ -0,0 +1,20 @@ +libmakepkg_module = 'lint_package' + +sources = [ + 'build_references.sh.in', + 'dotfiles.sh.in', + 'file_names.sh.in', + 'missing_backup.sh.in', +] + +foreach src : sources + output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module) + + custom_target( + libmakepkg_module + '_' + src.underscorify(), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : src, + output : '@BASENAME@', + install : true, + install_dir : output_dir) +endforeach diff --git a/scripts/libmakepkg/lint_pkgbuild/meson.build b/scripts/libmakepkg/lint_pkgbuild/meson.build new file mode 100644 index 00000000..9067c9d6 --- /dev/null +++ b/scripts/libmakepkg/lint_pkgbuild/meson.build @@ -0,0 +1,37 @@ +libmakepkg_module = 'lint_pkgbuild' + +sources = [ + 'arch.sh.in', + 'backup.sh.in', + 'changelog.sh.in', + 'checkdepends.sh.in', + 'conflicts.sh.in', + 'depends.sh.in', + 'epoch.sh.in', + 'install.sh.in', + 'makedepends.sh.in', + 'optdepends.sh.in', + 'options.sh.in', + 'package_function.sh.in', + 'pkgbase.sh.in', + 'pkglist.sh.in', + 'pkgname.sh.in', + 'pkgrel.sh.in', + 'pkgver.sh.in', + 'provides.sh.in', + 'source.sh.in', + 'util.sh.in', + 'variable.sh.in', +] + +foreach src : sources + output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module) + + custom_target( + libmakepkg_module + '_' + src.underscorify(), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : src, + output : '@BASENAME@', + install : true, + install_dir : output_dir) +endforeach diff --git a/scripts/libmakepkg/meson.build b/scripts/libmakepkg/meson.build new file mode 100644 index 00000000..07475b4d --- /dev/null +++ b/scripts/libmakepkg/meson.build @@ -0,0 +1,31 @@ +libmakepkg_modules = [ + { 'name' : 'integrity', 'has_subdir' : true }, + { 'name' : 'lint_config', 'has_subdir' : true }, + { 'name' : 'lint_package', 'has_subdir' : true }, + { 'name' : 'lint_pkgbuild', 'has_subdir' : true }, + { 'name' : 'source', 'has_subdir' : true }, + { 'name' : 'srcinfo', }, + { 'name' : 'tidy', 'has_subdir' : true }, + { 'name' : 'util', 'has_subdir' : true }, +] + +mkdir_p = 'mkdir -p $DESTDIR/@0@' + +foreach module : libmakepkg_modules + custom_target( + 'libmakepkg_@0@'.format(module['name']), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : '@0@.sh.in'.format(module['name']), + output : '@BASENAME@', + install : true, + install_dir : join_paths(get_option('datadir'), 'makepkg')) + + if module.get('has_subdir', false) + subdir(module['name']) + path = join_paths(get_option('prefix'), + get_option('datadir'), + 'makepkg', + module['name']) + meson.add_install_script('sh', '-c', mkdir_p.format(path)) + endif +endforeach diff --git a/scripts/libmakepkg/source/meson.build b/scripts/libmakepkg/source/meson.build new file mode 100644 index 00000000..59326133 --- /dev/null +++ b/scripts/libmakepkg/source/meson.build @@ -0,0 +1,22 @@ +libmakepkg_module = 'source' + +sources = [ + 'bzr.sh.in', + 'file.sh.in', + 'git.sh.in', + 'hg.sh.in', + 'local.sh.in', + 'svn.sh.in', +] + +foreach src : sources + output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module) + + custom_target( + libmakepkg_module + '_' + src.underscorify(), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : src, + output : '@BASENAME@', + install : true, + install_dir : output_dir) +endforeach diff --git a/scripts/libmakepkg/tidy/meson.build b/scripts/libmakepkg/tidy/meson.build new file mode 100644 index 00000000..052ac7a2 --- /dev/null +++ b/scripts/libmakepkg/tidy/meson.build @@ -0,0 +1,23 @@ +libmakepkg_module = 'tidy' + +sources = [ + 'docs.sh.in', + 'emptydirs.sh.in', + 'libtool.sh.in', + 'purge.sh.in', + 'staticlibs.sh.in', + 'strip.sh.in', + 'zipman.sh.in', +] + +foreach src : sources + output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module) + + custom_target( + libmakepkg_module + '_' + src.underscorify(), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : src, + output : '@BASENAME@', + install : true, + install_dir : output_dir) +endforeach diff --git a/scripts/libmakepkg/util/meson.build b/scripts/libmakepkg/util/meson.build new file mode 100644 index 00000000..b0e829c4 --- /dev/null +++ b/scripts/libmakepkg/util/meson.build @@ -0,0 +1,24 @@ +libmakepkg_module = 'util' + +sources = [ + 'compress.sh.in', + 'error.sh.in', + 'message.sh.in', + 'option.sh.in', + 'parseopts.sh.in', + 'pkgbuild.sh.in', + 'source.sh.in', + 'util.sh.in', +] + +foreach src : sources + output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module) + + custom_target( + libmakepkg_module + '_' + src.underscorify(), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : src, + output : '@BASENAME@', + install : true, + install_dir : output_dir) +endforeach diff --git a/scripts/meson.build b/scripts/meson.build new file mode 100644 index 00000000..1fe3fb78 --- /dev/null +++ b/scripts/meson.build @@ -0,0 +1,66 @@ +scripts = [ + 'makepkg-template.pl.in', + 'makepkg.sh.in', + 'pacman-db-upgrade.sh.in', + 'pacman-key.sh.in', + 'pkgdelta.sh.in', + 'repo-add.sh.in' +] + +library_files = [ + 'library/human_to_size.sh', + 'library/size_to_human.sh', +] + +SCRIPT_EDITOR = find_program(configure_file( + input : join_paths(meson.source_root(), 'build-aux/edit-script.sh.in'), + output : 'edit-script.sh', + configuration : substs)) + +m4_edit = generator( + M4, + arguments : ['-P', '-I', meson.current_source_dir(), '@INPUT@'], + output : '@PLAINNAME@', + capture : true) + +foreach script : scripts + custom_target( + script, + input : m4_edit.process(script), + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@', '0755'], + output : script.split('.')[0], + depend_files : library_files, + install : true, + install_dir : get_option('bindir')) +endforeach + +foreach symlink : ['repo-remove', 'repo-elephant'] + meson.add_install_script(MESON_MAKE_SYMLINK, + 'repo-add', + join_paths(BINDIR, symlink)) +endforeach + +subdir('libmakepkg') + +custom_target( + 'bash_completion', + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : 'completion/bash_completion.in', + output : 'pacman', + install : true, + install_dir : BASHCOMPDIR) + +foreach symlink : ['pacman-key', 'makepkg'] + meson.add_install_script(MESON_MAKE_SYMLINK, + 'pacman', + join_paths(BASHCOMPDIR, symlink)) +endforeach + +zsh_completion_dir = join_paths(DATAROOTDIR, 'zsh/site-functions') +custom_target( + 'zsh_completion', + command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ], + input : 'completion/zsh_completion.in', + output : '_pacman', + install : true, + install_dir : zsh_completion_dir) diff --git a/scripts/po/meson.build b/scripts/po/meson.build new file mode 100644 index 00000000..d8b8c51c --- /dev/null +++ b/scripts/po/meson.build @@ -0,0 +1,15 @@ +i18n.gettext( + 'pacman-scripts', + args : [ + '--directory=@0@'.format(meson.current_source_dir()), + '--msgid-bugs-address=http://bugs.archlinux.org/index.php?project=3', + '--copyright-holder="Pacman Development Team <pacman-dev@archlinux.org>"', + '--language', 'shell', + + '--keyword=_', + '--flag=_:1:c-format', + + '--keyword=_n:1,2', + '--flag=_n:1:c-format', + '--flag=_n:2:c-format', + ]) diff --git a/src/common/meson.build b/src/common/meson.build new file mode 100644 index 00000000..1443be3b --- /dev/null +++ b/src/common/meson.build @@ -0,0 +1,4 @@ +libcommon_sources = files(''' + ini.c ini.h + util-common.c util-common.h +'''.split()) diff --git a/src/pacman/meson.build b/src/pacman/meson.build new file mode 100644 index 00000000..6926f676 --- /dev/null +++ b/src/pacman/meson.build @@ -0,0 +1,23 @@ +pacman_sources = files(''' + check.h check.c + conf.h conf.c + database.c + deptest.c + files.c + package.h package.c + pacman.h pacman.c + query.c + remove.c + sighandler.h sighandler.c + sync.c + callback.h callback.c + upgrade.c + util.h util.c +'''.split()) + +pacman_conf_sources = files(''' + pacman-conf.c + util.h util.c + callback.h callback.c + conf.h conf.c +'''.split()) diff --git a/src/pacman/po/meson.build b/src/pacman/po/meson.build new file mode 100644 index 00000000..eb45fa1c --- /dev/null +++ b/src/pacman/po/meson.build @@ -0,0 +1,15 @@ +i18n.gettext( + 'pacman', + args : [ + '--directory=@0@'.format(meson.current_source_dir()), + '--msgid-bugs-address=http://bugs.archlinux.org/index.php?project=3', + '--copyright-holder="Pacman Development Team <pacman-dev@archlinux.org>"', + '--language', 'c', + + '--keyword=_', + '--flag=_:1:c-format', + + '--keyword=_n:1,2', + '--flag=_n:1:c-format', + '--flag=_n:2:c-format', + ]) diff --git a/src/util/meson.build b/src/util/meson.build new file mode 100644 index 00000000..cc219670 --- /dev/null +++ b/src/util/meson.build @@ -0,0 +1,3 @@ +cleanupdelta_sources = files('cleanupdelta.c') +testpkg_sources = files('testpkg.c') +vercmp_sources = files('vercmp.c') diff --git a/test/pacman/meson.build b/test/pacman/meson.build new file mode 100644 index 00000000..dbdb429e --- /dev/null +++ b/test/pacman/meson.build @@ -0,0 +1,357 @@ +pacman_tests = [ + { 'name': 'tests/backup001.py' }, + { 'name': 'tests/clean001.py' }, + { 'name': 'tests/clean002.py' }, + { 'name': 'tests/clean003.py' }, + { 'name': 'tests/clean004.py' }, + { 'name': 'tests/clean005.py' }, + { 'name': 'tests/config001.py' }, + { 'name': 'tests/config002.py' }, + { 'name': 'tests/database001.py' }, + { 'name': 'tests/database002.py' }, + { 'name': 'tests/database010.py' }, + { 'name': 'tests/database011.py' }, + { 'name': 'tests/database012.py' }, + { 'name': 'tests/dbonly-extracted-files.py' }, + { 'name': 'tests/depconflict100.py' }, + { 'name': 'tests/depconflict110.py' }, + { 'name': 'tests/depconflict111.py' }, + { 'name': 'tests/depconflict120.py' }, + { 'name': 'tests/dependency-cycle-fixed-by-upgrade.py' }, + { 'name': 'tests/deprange001.py', + 'should_fail': true }, + { 'name': 'tests/deptest001.py' }, + { 'name': 'tests/dummy001.py' }, + { 'name': 'tests/epoch001.py' }, + { 'name': 'tests/epoch002.py' }, + { 'name': 'tests/epoch003.py' }, + { 'name': 'tests/epoch004.py' }, + { 'name': 'tests/epoch005.py' }, + { 'name': 'tests/epoch010.py' }, + { 'name': 'tests/epoch011.py' }, + { 'name': 'tests/epoch012.py' }, + { 'name': 'tests/file-conflict-with-installed-pkg.py' }, + { 'name': 'tests/fileconflict001.py' }, + { 'name': 'tests/fileconflict002.py' }, + { 'name': 'tests/fileconflict003.py' }, + { 'name': 'tests/fileconflict004.py' }, + { 'name': 'tests/fileconflict005.py' }, + { 'name': 'tests/fileconflict006.py' }, + { 'name': 'tests/fileconflict007.py' }, + { 'name': 'tests/fileconflict008.py' }, + { 'name': 'tests/fileconflict009.py' }, + { 'name': 'tests/fileconflict010.py' }, + { 'name': 'tests/fileconflict011.py' }, + { 'name': 'tests/fileconflict012.py' }, + { 'name': 'tests/fileconflict013.py' }, + { 'name': 'tests/fileconflict015.py' }, + { 'name': 'tests/fileconflict016.py' }, + { 'name': 'tests/fileconflict017.py' }, + { 'name': 'tests/fileconflict020.py' }, + { 'name': 'tests/fileconflict021.py' }, + { 'name': 'tests/fileconflict022.py' }, + { 'name': 'tests/fileconflict023.py' }, + { 'name': 'tests/fileconflict024.py' }, + { 'name': 'tests/fileconflict025.py' }, + { 'name': 'tests/fileconflict030.py' }, + { 'name': 'tests/fileconflict031.py' }, + { 'name': 'tests/fileconflict032.py' }, + { 'name': 'tests/hook-abortonfail.py' }, + { 'name': 'tests/hook-description-reused.py' }, + { 'name': 'tests/hook-exec-reused.py' }, + { 'name': 'tests/hook-exec-with-arguments.py' }, + { 'name': 'tests/hook-file-change-packages.py' }, + { 'name': 'tests/hook-file-remove-trigger-match.py' }, + { 'name': 'tests/hook-file-upgrade-nomatch.py' }, + { 'name': 'tests/hook-invalid-trigger.py' }, + { 'name': 'tests/hook-pkg-install-trigger-match.py' }, + { 'name': 'tests/hook-pkg-postinstall-trigger-match.py' }, + { 'name': 'tests/hook-pkg-remove-trigger-match.py' }, + { 'name': 'tests/hook-pkg-upgrade-trigger-match.py' }, + { 'name': 'tests/hook-target-list.py' }, + { 'name': 'tests/hook-type-reused.py' }, + { 'name': 'tests/hook-upgrade-trigger-no-match.py' }, + { 'name': 'tests/hook-when-reused.py' }, + { 'name': 'tests/ignore001.py' }, + { 'name': 'tests/ignore002.py' }, + { 'name': 'tests/ignore003.py' }, + { 'name': 'tests/ignore004.py' }, + { 'name': 'tests/ignore005.py' }, + { 'name': 'tests/ignore006.py' }, + { 'name': 'tests/ignore007.py' }, + { 'name': 'tests/ignore008.py' }, + { 'name': 'tests/ldconfig001.py' }, + { 'name': 'tests/ldconfig002.py' }, + { 'name': 'tests/ldconfig003.py' }, + { 'name': 'tests/mode001.py' }, + { 'name': 'tests/mode002.py' }, + { 'name': 'tests/mode003.py' }, + { 'name': 'tests/noupgrade-inverted.py' }, + { 'name': 'tests/overwrite-files-match-negated.py' }, + { 'name': 'tests/overwrite-files-match.py' }, + { 'name': 'tests/overwrite-files-nonmatch.py' }, + { 'name': 'tests/pacman001.py' }, + { 'name': 'tests/pacman002.py' }, + { 'name': 'tests/pacman003.py' }, + { 'name': 'tests/pacman004.py' }, + { 'name': 'tests/pacman005.py' }, + { 'name': 'tests/provision001.py' }, + { 'name': 'tests/provision002.py' }, + { 'name': 'tests/provision003.py' }, + { 'name': 'tests/provision004.py' }, + { 'name': 'tests/provision010.py' }, + { 'name': 'tests/provision011.py' }, + { 'name': 'tests/provision012.py' }, + { 'name': 'tests/provision020.py' }, + { 'name': 'tests/provision021.py' }, + { 'name': 'tests/provision022.py' }, + { 'name': 'tests/query001.py' }, + { 'name': 'tests/query002.py' }, + { 'name': 'tests/query003.py' }, + { 'name': 'tests/query004.py' }, + { 'name': 'tests/query005.py' }, + { 'name': 'tests/query006.py', + # expect failure on 32 bit machines + 'should_fail': cc.sizeof('ssize_t') < 8 }, + { 'name': 'tests/query007.py' }, + { 'name': 'tests/query010.py' }, + { 'name': 'tests/query011.py' }, + { 'name': 'tests/query012.py' }, + { 'name': 'tests/querycheck001.py' }, + { 'name': 'tests/querycheck002.py' }, + { 'name': 'tests/querycheck_fast_file_type.py' }, + { 'name': 'tests/reason001.py' }, + { 'name': 'tests/remove-assumeinstalled.py' }, + { 'name': 'tests/remove-directory-replaced-with-symlink.py' }, + { 'name': 'tests/remove-optdepend-of-installed-package.py' }, + { 'name': 'tests/remove-recursive-cycle.py' }, + { 'name': 'tests/remove001.py' }, + { 'name': 'tests/remove002.py' }, + { 'name': 'tests/remove010.py' }, + { 'name': 'tests/remove011.py' }, + { 'name': 'tests/remove012.py' }, + { 'name': 'tests/remove020.py' }, + { 'name': 'tests/remove021.py' }, + { 'name': 'tests/remove030.py' }, + { 'name': 'tests/remove031.py' }, + { 'name': 'tests/remove040.py' }, + { 'name': 'tests/remove041.py' }, + { 'name': 'tests/remove042.py' }, + { 'name': 'tests/remove043.py' }, + { 'name': 'tests/remove044.py' }, + { 'name': 'tests/remove045.py' }, + { 'name': 'tests/remove047.py' }, + { 'name': 'tests/remove049.py' }, + { 'name': 'tests/remove050.py' }, + { 'name': 'tests/remove051.py' }, + { 'name': 'tests/remove052.py' }, + { 'name': 'tests/remove060.py' }, + { 'name': 'tests/remove070.py' }, + { 'name': 'tests/remove071.py' }, + { 'name': 'tests/replace100.py' }, + { 'name': 'tests/replace101.py' }, + { 'name': 'tests/replace102.py' }, + { 'name': 'tests/replace103.py' }, + { 'name': 'tests/replace104.py' }, + { 'name': 'tests/replace110.py', + 'should_fail': true }, + { 'name': 'tests/scriptlet001.py' }, + { 'name': 'tests/scriptlet002.py' }, + { 'name': 'tests/sign001.py' }, + { 'name': 'tests/sign002.py' }, + { 'name': 'tests/skip-remove-with-glob-chars.py' }, + { 'name': 'tests/smoke001.py' }, + { 'name': 'tests/smoke002.py' }, + { 'name': 'tests/smoke003.py' }, + { 'name': 'tests/smoke004.py' }, + { 'name': 'tests/symlink-replace-with-dir.py' }, + { 'name': 'tests/symlink001.py' }, + { 'name': 'tests/symlink002.py' }, + { 'name': 'tests/symlink010.py' }, + { 'name': 'tests/symlink011.py' }, + { 'name': 'tests/symlink012.py' }, + { 'name': 'tests/symlink020.py' }, + { 'name': 'tests/symlink021.py' }, + { 'name': 'tests/sync-install-assumeinstalled.py' }, + { 'name': 'tests/sync-nodepversion01.py' }, + { 'name': 'tests/sync-nodepversion02.py' }, + { 'name': 'tests/sync-nodepversion03.py' }, + { 'name': 'tests/sync-nodepversion04.py' }, + { 'name': 'tests/sync-nodepversion05.py' }, + { 'name': 'tests/sync-nodepversion06.py' }, + { 'name': 'tests/sync-sysupgrade-print-replaced-packages.py' }, + { 'name': 'tests/sync-update-assumeinstalled.py' }, + { 'name': 'tests/sync-update-package-removing-required-provides.py', + 'should_fail': true }, + { 'name': 'tests/sync001.py' }, + { 'name': 'tests/sync002.py' }, + { 'name': 'tests/sync003.py' }, + { 'name': 'tests/sync009.py' }, + { 'name': 'tests/sync010.py' }, + { 'name': 'tests/sync011.py' }, + { 'name': 'tests/sync012.py' }, + { 'name': 'tests/sync020.py' }, + { 'name': 'tests/sync021.py' }, + { 'name': 'tests/sync022.py' }, + { 'name': 'tests/sync023.py' }, + { 'name': 'tests/sync024.py' }, + { 'name': 'tests/sync030.py' }, + { 'name': 'tests/sync031.py' }, + { 'name': 'tests/sync040.py' }, + { 'name': 'tests/sync041.py' }, + { 'name': 'tests/sync042.py' }, + { 'name': 'tests/sync043.py' }, + { 'name': 'tests/sync044.py' }, + { 'name': 'tests/sync045.py' }, + { 'name': 'tests/sync046.py' }, + { 'name': 'tests/sync050.py' }, + { 'name': 'tests/sync051.py' }, + { 'name': 'tests/sync052.py' }, + { 'name': 'tests/sync100.py' }, + { 'name': 'tests/sync1000.py' }, + { 'name': 'tests/sync1003.py' }, + { 'name': 'tests/sync1004.py' }, + { 'name': 'tests/sync1008.py' }, + { 'name': 'tests/sync101.py' }, + { 'name': 'tests/sync102.py' }, + { 'name': 'tests/sync103.py' }, + { 'name': 'tests/sync104.py' }, + { 'name': 'tests/sync110.py' }, + { 'name': 'tests/sync1100.py' }, + { 'name': 'tests/sync1101.py' }, + { 'name': 'tests/sync1102.py' }, + { 'name': 'tests/sync1103.py' }, + { 'name': 'tests/sync1104.py' }, + { 'name': 'tests/sync1105.py' }, + { 'name': 'tests/sync120.py' }, + { 'name': 'tests/sync130.py' }, + { 'name': 'tests/sync131.py' }, + { 'name': 'tests/sync132.py' }, + { 'name': 'tests/sync133.py' }, + { 'name': 'tests/sync134.py' }, + { 'name': 'tests/sync135.py' }, + { 'name': 'tests/sync136.py' }, + { 'name': 'tests/sync137.py' }, + { 'name': 'tests/sync138.py' }, + { 'name': 'tests/sync139.py' }, + { 'name': 'tests/sync140.py' }, + { 'name': 'tests/sync141.py' }, + { 'name': 'tests/sync150.py' }, + { 'name': 'tests/sync200.py' }, + { 'name': 'tests/sync300.py' }, + { 'name': 'tests/sync306.py' }, + { 'name': 'tests/sync400.py' }, + { 'name': 'tests/sync401.py' }, + { 'name': 'tests/sync402.py' }, + { 'name': 'tests/sync403.py', + 'should_fail': true }, + { 'name': 'tests/sync404.py' }, + { 'name': 'tests/sync405.py' }, + { 'name': 'tests/sync406.py', + 'should_fail': true }, + { 'name': 'tests/sync407.py' }, + { 'name': 'tests/sync500.py' }, + { 'name': 'tests/sync501.py' }, + { 'name': 'tests/sync502.py' }, + { 'name': 'tests/sync503.py' }, + { 'name': 'tests/sync600.py' }, + { 'name': 'tests/sync700.py' }, + { 'name': 'tests/sync701.py' }, + { 'name': 'tests/sync702.py' }, + { 'name': 'tests/sync890.py' }, + { 'name': 'tests/sync891.py' }, + { 'name': 'tests/sync892.py' }, + { 'name': 'tests/sync893.py' }, + { 'name': 'tests/sync895.py' }, + { 'name': 'tests/sync896.py' }, + { 'name': 'tests/sync897.py' }, + { 'name': 'tests/sync898.py' }, + { 'name': 'tests/sync899.py' }, + { 'name': 'tests/sync900.py' }, + { 'name': 'tests/sync901.py' }, + { 'name': 'tests/sync990.py' }, + { 'name': 'tests/sync992.py' }, + { 'name': 'tests/sync993.py' }, + { 'name': 'tests/sync999.py' }, + { 'name': 'tests/trans001.py' }, + { 'name': 'tests/type001.py' }, + { 'name': 'tests/unresolvable001.py' }, + { 'name': 'tests/upgrade001.py' }, + { 'name': 'tests/upgrade002.py' }, + { 'name': 'tests/upgrade003.py' }, + { 'name': 'tests/upgrade004.py' }, + { 'name': 'tests/upgrade005.py' }, + { 'name': 'tests/upgrade006.py' }, + { 'name': 'tests/upgrade010.py' }, + { 'name': 'tests/upgrade011.py' }, + { 'name': 'tests/upgrade013.py' }, + { 'name': 'tests/upgrade020.py' }, + { 'name': 'tests/upgrade021.py' }, + { 'name': 'tests/upgrade022.py' }, + { 'name': 'tests/upgrade023.py' }, + { 'name': 'tests/upgrade024.py' }, + { 'name': 'tests/upgrade025.py' }, + { 'name': 'tests/upgrade026.py' }, + { 'name': 'tests/upgrade027.py' }, + { 'name': 'tests/upgrade028.py' }, + { 'name': 'tests/upgrade029.py' }, + { 'name': 'tests/upgrade030.py' }, + { 'name': 'tests/upgrade031.py' }, + { 'name': 'tests/upgrade032.py' }, + { 'name': 'tests/upgrade040.py' }, + { 'name': 'tests/upgrade041.py' }, + { 'name': 'tests/upgrade042.py' }, + { 'name': 'tests/upgrade043.py' }, + { 'name': 'tests/upgrade045.py' }, + { 'name': 'tests/upgrade050.py' }, + { 'name': 'tests/upgrade051.py' }, + { 'name': 'tests/upgrade052.py' }, + { 'name': 'tests/upgrade053.py' }, + { 'name': 'tests/upgrade054.py' }, + { 'name': 'tests/upgrade055.py' }, + { 'name': 'tests/upgrade056.py' }, + { 'name': 'tests/upgrade057.py' }, + { 'name': 'tests/upgrade058.py' }, + { 'name': 'tests/upgrade059.py' }, + { 'name': 'tests/upgrade060.py' }, + { 'name': 'tests/upgrade061.py' }, + { 'name': 'tests/upgrade070.py' }, + { 'name': 'tests/upgrade071.py' }, + { 'name': 'tests/upgrade072.py' }, + { 'name': 'tests/upgrade073.py' }, + { 'name': 'tests/upgrade074.py' }, + { 'name': 'tests/upgrade075.py' }, + { 'name': 'tests/upgrade076.py' }, + { 'name': 'tests/upgrade077.py' }, + { 'name': 'tests/upgrade078.py', + 'should_fail': true }, + { 'name': 'tests/upgrade080.py' }, + { 'name': 'tests/upgrade081.py' }, + { 'name': 'tests/upgrade082.py' }, + { 'name': 'tests/upgrade083.py' }, + { 'name': 'tests/upgrade084.py' }, + { 'name': 'tests/upgrade090.py' }, + { 'name': 'tests/upgrade100.py' }, + { 'name': 'tests/xfercommand001.py' }, +] + +foreach testobj : pacman_tests + input = testobj.get('name') + test_name = input.split('/')[1] + should_fail = testobj.get('should_fail', false) + + test( + test_name, + PYTHON, + args : [ + join_paths(meson.source_root(), 'build-aux/tap-driver.py'), + join_paths(meson.current_source_dir(), 'pactest.py'), + '--scriptlet-shell', get_option('scriptlet-shell'), + '--bindir', meson.build_root(), + '--ldconfig', LDCONFIG, + '--verbose', + join_paths(meson.current_source_dir(), input) + ], + depends : [pacman_bin], + should_fail : should_fail) +endforeach diff --git a/test/scripts/meson.build b/test/scripts/meson.build new file mode 100644 index 00000000..6d6194dd --- /dev/null +++ b/test/scripts/meson.build @@ -0,0 +1,12 @@ +tests = [ + 'parseopts_test.sh', + 'makepkg-template_test.sh', + 'human_to_size_test.sh', +] + +foreach tst : tests + test(tst, + BASH, + env : TEST_ENV, + args : [join_paths(meson.current_source_dir(), tst)]) +endforeach diff --git a/test/util/meson.build b/test/util/meson.build new file mode 100644 index 00000000..07b29e5c --- /dev/null +++ b/test/util/meson.build @@ -0,0 +1,6 @@ +test('vercmptest', + BASH, + env : TEST_ENV, + args : [ + join_paths(meson.current_source_dir(), 'vercmptest.sh') + ]) -- 2.19.1
On 22/10/18 7:46 am, Dave Reisner wrote:
3) No 'make dist' equivalent. Just run 'git archive' to generate a suitable tarball for distribution.
Is there a way to include pregenerated man pages with git archive? A
On Mon, Oct 22, 2018 at 07:54:57AM +1000, Allan McRae wrote:
On 22/10/18 7:46 am, Dave Reisner wrote:
3) No 'make dist' equivalent. Just run 'git archive' to generate a suitable tarball for distribution.
Is there a way to include pregenerated man pages with git archive?
A
No, git archive only considers what's in the git tree. Is there a reason we're determined to pre-generate the manpages instead of just adding makedepends on ascididoc?
On 10/21/18 6:12 PM, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 07:54:57AM +1000, Allan McRae wrote:
On 22/10/18 7:46 am, Dave Reisner wrote:
3) No 'make dist' equivalent. Just run 'git archive' to generate a suitable tarball for distribution.
Is there a way to include pregenerated man pages with git archive?
A
No, git archive only considers what's in the git tree. Is there a reason we're determined to pre-generate the manpages instead of just adding makedepends on ascididoc?
I've got a better question, shouldn't we explicitly want to generate them at build time? The output depends on buildtime options -- it uses pkgdatadir, localstatedir, sysconfdir, datarootdir to redefine paths in the manpages. -- Eli Schwartz Bug Wrangler and Trusted User
On 22/10/18 8:12 am, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 07:54:57AM +1000, Allan McRae wrote:
On 22/10/18 7:46 am, Dave Reisner wrote:
3) No 'make dist' equivalent. Just run 'git archive' to generate a suitable tarball for distribution.
Is there a way to include pregenerated man pages with git archive?
A
No, git archive only considers what's in the git tree. Is there a reason we're determined to pre-generate the manpages instead of just adding makedepends on ascididoc?
I think providing prebuilt man pages is more important now we require python3 for testing given asciidoc requires python2. Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option. Allan
On 10/21/18 6:26 PM, Allan McRae wrote:
On 22/10/18 8:12 am, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 07:54:57AM +1000, Allan McRae wrote:
On 22/10/18 7:46 am, Dave Reisner wrote:
3) No 'make dist' equivalent. Just run 'git archive' to generate a suitable tarball for distribution.
Is there a way to include pregenerated man pages with git archive?
A
No, git archive only considers what's in the git tree. Is there a reason we're determined to pre-generate the manpages instead of just adding makedepends on ascididoc?
I think providing prebuilt man pages is more important now we require python3 for testing given asciidoc requires python2.
Maybe by the time we fully commit to meson, this will be ready for public release: https://github.com/asciidoc/asciidoc-py3 In fact, currently, Fedora uses it -- though via some sort of nonexistent tag or something. :/
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files... -- Eli Schwartz Bug Wrangler and Trusted User
On 22/10/18 8:57 am, Eli Schwartz wrote:
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files...
That is another good reason not to use git archive to create release tarballs. A
On Mon, Oct 22, 2018 at 09:56:04AM +1000, Allan McRae wrote:
On 22/10/18 8:57 am, Eli Schwartz wrote:
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files...
That is another good reason not to use git archive to create release tarballs.
A
Consider that the reason we need 'make dist' and can't just use 'git archive' is because autotools *requires* extra tooling around just to generate the build system. This is no longer needed with meson. Pre-generating the manpages means that our substitutions are invalidated. For example, someone building from the tarball with --prefix=/some/where/else or no --prefix at all will have a pacman.conf(5) that still claims the right path is /etc/pacman.conf I understand your point about python2 vs python3, but I think that's something we can work out based on a python3-based asciidoc in existance. What problems here would you like to see solved for the inclusion of meson? That will help me focus my time spent on this. dR
On 22/10/18 10:03 am, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 09:56:04AM +1000, Allan McRae wrote:
On 22/10/18 8:57 am, Eli Schwartz wrote:
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files...
That is another good reason not to use git archive to create release tarballs.
A
Consider that the reason we need 'make dist' and can't just use 'git archive' is because autotools *requires* extra tooling around just to generate the build system. This is no longer needed with meson.
Good point! I'm not overly familiar with meson, so missed that completely.
Pre-generating the manpages means that our substitutions are invalidated. For example, someone building from the tarball with --prefix=/some/where/else or no --prefix at all will have a pacman.conf(5) that still claims the right path is /etc/pacman.conf
I understand your point about python2 vs python3, but I think that's something we can work out based on a python3-based asciidoc in existance.
Does the meson build script allow us to not create docs if wanted?
What problems here would you like to see solved for the inclusion of meson? That will help me focus my time spent on this.
None need solved for inclusion in the current state. I'm just trying to understand what our future release process will look like. While we have autotools in parallel, if I run "make dist" with this patch, do all the needed meson files get included too? Can we get a helper script to run doxygen? Thanks, Allan
On 10/21/18 9:16 PM, Allan McRae wrote:
On 22/10/18 10:03 am, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 09:56:04AM +1000, Allan McRae wrote:
On 22/10/18 8:57 am, Eli Schwartz wrote:
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files...
That is another good reason not to use git archive to create release tarballs.
A
Consider that the reason we need 'make dist' and can't just use 'git archive' is because autotools *requires* extra tooling around just to generate the build system. This is no longer needed with meson.
Good point! I'm not overly familiar with meson, so missed that completely.
Pre-generating the manpages means that our substitutions are invalidated. For example, someone building from the tarball with --prefix=/some/where/else or no --prefix at all will have a pacman.conf(5) that still claims the right path is /etc/pacman.conf
I understand your point about python2 vs python3, but I think that's something we can work out based on a python3-based asciidoc in existance.
Does the meson build script allow us to not create docs if wanted?
Yes, it does. The file meson_options.txt is used as a central location to list all options, their description, and default values -- which is nicely readable too, slightly unlike configure.ac. :)
What problems here would you like to see solved for the inclusion of meson? That will help me focus my time spent on this.
None need solved for inclusion in the current state. I'm just trying to understand what our future release process will look like.
While we have autotools in parallel, if I run "make dist" with this patch, do all the needed meson files get included too? Can we get a helper script to run doxygen?
No, I think this is entirely down to EXTRA_DIST in Makefile.am, but specifying "meson_options.txt meson.build" might be enough. -- Eli Schwartz Bug Wrangler and Trusted User
On 10/21/18 9:32 PM, Eli Schwartz wrote:
On 10/21/18 9:16 PM, Allan McRae wrote:
None need solved for inclusion in the current state. I'm just trying to understand what our future release process will look like.
While we have autotools in parallel, if I run "make dist" with this patch, do all the needed meson files get included too? Can we get a helper script to run doxygen?
No, I think this is entirely down to EXTRA_DIST in Makefile.am, but specifying "meson_options.txt meson.build" might be enough.
Nope, not only does this not include the new files in build-aux, autotools also only matches this file in the current directorya. So, time to hardcode a long list of files... -- Eli Schwartz Bug Wrangler and Trusted User
On Mon, Oct 22, 2018 at 11:16:25AM +1000, Allan McRae wrote:
On 22/10/18 10:03 am, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 09:56:04AM +1000, Allan McRae wrote:
On 22/10/18 8:57 am, Eli Schwartz wrote:
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files...
That is another good reason not to use git archive to create release tarballs.
A
Consider that the reason we need 'make dist' and can't just use 'git archive' is because autotools *requires* extra tooling around just to generate the build system. This is no longer needed with meson.
Good point! I'm not overly familiar with meson, so missed that completely.
Pre-generating the manpages means that our substitutions are invalidated. For example, someone building from the tarball with --prefix=/some/where/else or no --prefix at all will have a pacman.conf(5) that still claims the right path is /etc/pacman.conf
I understand your point about python2 vs python3, but I think that's something we can work out based on a python3-based asciidoc in existance.
Does the meson build script allow us to not create docs if wanted?
Yes, see the meson_options.txt as part of this patch. One can invoke meson with -Ddoc=disabled to prevent manpages from being built.
What problems here would you like to see solved for the inclusion of meson? That will help me focus my time spent on this.
None need solved for inclusion in the current state. I'm just trying to understand what our future release process will look like.
Great!
While we have autotools in parallel, if I run "make dist" with this patch, do all the needed meson files get included too? Can we get a helper script to run doxygen?
No, meson.build files will not be included with the autotools-built 'make dist' tarball. It feels weird to do this. I suspect that if we want to switch the Arch build over while this dual build-system world exists, we should just build from a tag in the git repo. Yes, I can add a script in build-aux to invoke doxygen. It's also possible I could create the Doxyfile as a .in file, and generate the right OUTPUT_DIRECTORY for invocation through the buildsys. There's actually an upstream example of exactly this: https://github.com/mesonbuild/meson/blob/master/test%20cases/frameworks/14%2... I'll look into options here.
Thanks, Allan
On Sun, Oct 21, 2018 at 10:11:18PM -0400, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 11:16:25AM +1000, Allan McRae wrote:
On 22/10/18 10:03 am, Dave Reisner wrote:
On Mon, Oct 22, 2018 at 09:56:04AM +1000, Allan McRae wrote:
On 22/10/18 8:57 am, Eli Schwartz wrote:
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files...
That is another good reason not to use git archive to create release tarballs.
A
Consider that the reason we need 'make dist' and can't just use 'git archive' is because autotools *requires* extra tooling around just to generate the build system. This is no longer needed with meson.
Good point! I'm not overly familiar with meson, so missed that completely.
Pre-generating the manpages means that our substitutions are invalidated. For example, someone building from the tarball with --prefix=/some/where/else or no --prefix at all will have a pacman.conf(5) that still claims the right path is /etc/pacman.conf
I understand your point about python2 vs python3, but I think that's something we can work out based on a python3-based asciidoc in existance.
Does the meson build script allow us to not create docs if wanted?
Yes, see the meson_options.txt as part of this patch. One can invoke meson with -Ddoc=disabled to prevent manpages from being built.
What problems here would you like to see solved for the inclusion of meson? That will help me focus my time spent on this.
None need solved for inclusion in the current state. I'm just trying to understand what our future release process will look like.
Great!
While we have autotools in parallel, if I run "make dist" with this patch, do all the needed meson files get included too? Can we get a helper script to run doxygen?
No, meson.build files will not be included with the autotools-built 'make dist' tarball. It feels weird to do this. I suspect that if we want to switch the Arch build over while this dual build-system world exists, we should just build from a tag in the git repo.
Yes, I can add a script in build-aux to invoke doxygen. It's also possible I could create the Doxyfile as a .in file, and generate the right OUTPUT_DIRECTORY for invocation through the buildsys. There's actually an upstream example of exactly this:
https://github.com/mesonbuild/meson/blob/master/test%20cases/frameworks/14%2...
I'll look into options here.
Figured this out, there's now a -Ddoxygen flag on the build system which will build and install the doxygen crap if wanted. Adding this requires a slight tweak on the autotools side to handle the Doxyfile -> Doxyfile.in rename and subsequent generation. dR
On 10/21/18 7:56 PM, Allan McRae wrote:
On 22/10/18 8:57 am, Eli Schwartz wrote:
Also, most projects ship prebuilt man pages. I think some GNU ones commit the built page to the tree, so that could be an option.
Both those things are also true about the configure and Makefile.in files...
That is another good reason not to use git archive to create release tarballs.
Well, the point I'm trying to make here is that they're connected. They ship prebuilt man pages because they're already forced into using make dist in order to generate the build system. The egregiously offensive ones even commit their autotools results to git which is pure madness... It's not pure madness to check manpages into git, but it also doesn't seem like a hugely important thing. Excepting projects that only provide troff-formatted manpages from the start, and autotools project where it doesn't prove anything, how many are left that provide pregenerated manpages? ... Anyway, given this patch is meant to provide an alternative to autotools, if we ever stop generating autotools dist tarballs it is because we don't need configure/Makefile.in anymore, in which case arguing based on that merit will be obsolete, and the only question to consider is the doc files specifically. For which we'll need to ask the question, did we ever need them in the first place or were we just used to having them as a byproduct of the previous build system requirements. I guess we have time to think about how to fully implement a dist target for meson, after getting it completed as a valid build target first... -- Eli Schwartz Bug Wrangler and Trusted User
On 10/21/18 at 05:46pm, Dave Reisner wrote: -- >8 -- (lots of words)
diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..3f9b2ae0 --- /dev/null +++ b/meson.build @@ -0,0 +1,487 @@
-- >8 -- (many more words)
+PYTHON = find_program('python')
This should look for python3, should it not? -- >8 -- (I really hope this was mostly copy-paste)
+libcommon = static_library( + 'common', + libcommon_sources, + install : false)
It's a mistake, but common/ini.c currently includes alpm.h, which grabs the system alpm.h, or dies if it's not installed, because this doesn't link_with libalpm. I'll send a patch to fix this particular error, but I can imagine this sort of subtle error creeping in again. Should we proactively link_with libalpm to prevent this from recurring? -- >8 -- (seriously, this patch is huge)
diff --git a/test/pacman/meson.build b/test/pacman/meson.build new file mode 100644 index 00000000..dbdb429e --- /dev/null +++ b/test/pacman/meson.build @@ -0,0 +1,357 @@ +pacman_tests = [ + { 'name': 'tests/backup001.py' },
Having the test list and expected success/failure duplicated here is almost certain to lead to meson and autotools getting out of sync. Can/should we dynamically create this list at least for as long as we're maintaining both build systems?
On Thu, Nov 01, 2018 at 01:03:27AM -0700, Andrew Gregory wrote:
On 10/21/18 at 05:46pm, Dave Reisner wrote:
-- >8 -- (lots of words)
diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..3f9b2ae0 --- /dev/null +++ b/meson.build @@ -0,0 +1,487 @@
-- >8 -- (many more words)
+PYTHON = find_program('python')
This should look for python3, should it not?
-- >8 -- (I really hope this was mostly copy-paste)
+libcommon = static_library( + 'common', + libcommon_sources, + install : false)
It's a mistake, but common/ini.c currently includes alpm.h, which grabs the system alpm.h, or dies if it's not installed, because this doesn't link_with libalpm. I'll send a patch to fix this particular error, but I can imagine this sort of subtle error creeping in again. Should we proactively link_with libalpm to prevent this from recurring?
I get what you're saying about ini.c wrongly including alpm.h, but I'm not sure I follow about linking with libalpm. Shouldn't the includes be fixed such that the inclusion of alpm.h comes from lib/libalpm rather than /usr/include? I'm not clear on what linking with the local libalpm accomplishes other than being an unnecessary dependency.
-- >8 -- (seriously, this patch is huge)
diff --git a/test/pacman/meson.build b/test/pacman/meson.build new file mode 100644 index 00000000..dbdb429e --- /dev/null +++ b/test/pacman/meson.build @@ -0,0 +1,357 @@ +pacman_tests = [ + { 'name': 'tests/backup001.py' },
Having the test list and expected success/failure duplicated here is almost certain to lead to meson and autotools getting out of sync. Can/should we dynamically create this list at least for as long as we're maintaining both build systems?
I'll think about how to do this... I'm not crazy about the idea of making configuration of the meson build anything more than just 'meson build', and this all needs to ready for processing at the time meson generates the inputs for ninja.
On 11/01/18 at 08:51pm, Dave Reisner wrote:
On Thu, Nov 01, 2018 at 01:03:27AM -0700, Andrew Gregory wrote:
On 10/21/18 at 05:46pm, Dave Reisner wrote:
...
+libcommon = static_library( + 'common', + libcommon_sources, + install : false)
It's a mistake, but common/ini.c currently includes alpm.h, which grabs the system alpm.h, or dies if it's not installed, because this doesn't link_with libalpm. I'll send a patch to fix this particular error, but I can imagine this sort of subtle error creeping in again. Should we proactively link_with libalpm to prevent this from recurring?
I get what you're saying about ini.c wrongly including alpm.h, but I'm not sure I follow about linking with libalpm. Shouldn't the includes be fixed such that the inclusion of alpm.h comes from lib/libalpm rather than /usr/include? I'm not clear on what linking with the local libalpm accomplishes other than being an unnecessary dependency.
I've still not played with meson enough to fully understand exactly how it works. The use of link_with was just to get meson to use lib/libalpm as an include dir. If there's a better way to do that, great, I just want to make sure that if a common file includes alpm.h in the future, it doesn't sneakily use the system copy.
On Thu, Nov 01, 2018 at 06:38:03PM -0700, Andrew Gregory wrote:
On 11/01/18 at 08:51pm, Dave Reisner wrote:
On Thu, Nov 01, 2018 at 01:03:27AM -0700, Andrew Gregory wrote:
On 10/21/18 at 05:46pm, Dave Reisner wrote:
...
+libcommon = static_library( + 'common', + libcommon_sources, + install : false)
It's a mistake, but common/ini.c currently includes alpm.h, which grabs the system alpm.h, or dies if it's not installed, because this doesn't link_with libalpm. I'll send a patch to fix this particular error, but I can imagine this sort of subtle error creeping in again. Should we proactively link_with libalpm to prevent this from recurring?
I get what you're saying about ini.c wrongly including alpm.h, but I'm not sure I follow about linking with libalpm. Shouldn't the includes be fixed such that the inclusion of alpm.h comes from lib/libalpm rather than /usr/include? I'm not clear on what linking with the local libalpm accomplishes other than being an unnecessary dependency.
I've still not played with meson enough to fully understand exactly how it works. The use of link_with was just to get meson to use lib/libalpm as an include dir. If there's a better way to do that, great, I just want to make sure that if a common file includes alpm.h in the future, it doesn't sneakily use the system copy.
Ah yes, we're saying the same thing. Fixed on my branch.
participants (5)
-
Allan McRae
-
Andrew Gregory
-
Dave Reisner
-
Dave Reisner
-
Eli Schwartz