Git commit 301b9b4caf1b84bf2e14bd616fec06683f5a2d18 by Andrew Shark. Committed on 17/02/2024 at 17:50. Pushed by ashark into branch 'master'.
Merge kdesrc-build --run and kdesrc-run This fixes multiple issues with kdesrc-run and kdesrc-build --run When using the --run parameter, the environment variables of global module were applied (from set-env options). But this is incorrect, since global cannot be treated as usual module. Its build system is defined as generic. In its prepareModuleBuildEnvironment these variables were setted: - PKG_CONFIG_PATH - LD_LIBRARY_PATH - PATH They have nothing to do with launched module's variables, except PATH, but even that was because of global install-dir matches the module's install-dir in most cases. The kdesrc-run did sourced module's prefix.sh instead (located in its build-dir). That setted the following variables: - PATH (the correct, from module) - XDG_DATA_DIRS - XDG_CONFIG_DIRS - QT_PLUGIN_PATH - QML2_IMPORT_PATH - QT_QUICK_CONTROLS_STYLE_PATH This commit fixes the broken behavior of --run, and the broken behavior of kdesrc-run. Fixes: #145 Fixes: #114 Other fixes: - Now the parameters after --run that starts with minuses are passed to the start-program, and not considered as options of kdesrc-build - When setting parameters to the runned executable, they are actually applied. Previously the run script surrounded the $@ in the quotes. - Fixed indentation and unnecessary semicolons in executable script. - Made more clear note information when launching. The debug level controls if it will be displayed. M +0 -1 CMakeLists.txt M +0 -1 README.md M +0 -1 completions/zsh/_kdesrc-build M +4 -4 data/kdesrc-run-completions.sh M +1 -1 doc/man-kdesrc-build.1.docbook M +3 -23 doc/supported-cmdline-params.docbook D +0 -134 kdesrc-run M +2 -40 modules/ksb/Application.pm M +22 -5 modules/ksb/Cmdline.pm A +122 -0 modules/ksb/StartProgram.pm M +2 -2 modules/ksb/TaskManager.pm M +1 -1 scripts/gen_zsh_completions.py https://invent.kde.org/sdk/kdesrc-build/-/commit/301b9b4caf1b84bf2e14bd616fec06683f5a2d18 diff --git a/CMakeLists.txt b/CMakeLists.txt index bae5fd53..03047adb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,6 @@ endif() # Currently, kdesrc-build real file (not a symlink) expects to be near its data and modules. Need to make a symlink in PKGBUILD then. install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/kdesrc-build DESTINATION ${KDE_INSTALL_DATADIR}/kdesrc-build) -install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/kdesrc-run DESTINATION ${KDE_INSTALL_DATADIR}/kdesrc-build) install(DIRECTORY data/ DESTINATION ${KDE_INSTALL_DATADIR}/kdesrc-build/data) diff --git a/README.md b/README.md index c95e6d8b..8f253dcc 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ For other distributions, you will need to make a local installation: $ cd ~/.local/share $ git clone https://invent.kde.org/sdk/kdesrc-build.git $ ln -sf ~/.local/share/kdesrc-build/kdesrc-build ~/.local/bin -$ ln -sf ~/.local/share/kdesrc-build/kdesrc-run ~/.local/bin ``` - Make sure it works by running: diff --git a/completions/zsh/_kdesrc-build b/completions/zsh/_kdesrc-build index bc8202e4..600811e8 100644 --- a/completions/zsh/_kdesrc-build +++ b/completions/zsh/_kdesrc-build @@ -75,7 +75,6 @@ _arguments \ "(--run-tests --no-run-tests)"{--run-tests,--no-run-tests}"[Built the modules with support for running their test suite]" \ "--set-module-option-value""[Override an option in your configuration file for a specific module]"":argument:" \ "--source-dir""[Directory that stores the KDE sources]"":argument:" \ - "(--run --start-program)"{--run,--start-program}"[A program to run with kdesrc-build]"":arguments:" \ "(--stop-on-failure --no-stop-on-failure)"{--stop-on-failure,--no-stop-on-failure}"[Stops/Does not stop the build as soon as a package fails to build]" \ "--tag""[Download a specific release of a module]"":argument:" \ "--uninstall""[Uninstalls the module]" \ diff --git a/data/kdesrc-run-completions.sh b/data/kdesrc-run-completions.sh index 47e222ff..820259e2 100644 --- a/data/kdesrc-run-completions.sh +++ b/data/kdesrc-run-completions.sh @@ -1,5 +1,5 @@ -## Autocomplete for kdesrc-run -function _comp_kdesrc_run +## Autocomplete for kdesrc-build --run +function _comp_kdesrc_build_run { local cur COMPREPLY=() @@ -10,7 +10,7 @@ function _comp_kdesrc_run return 0 fi - # Retrieve build modules through kdesrc-run + # Retrieve build modules through kdesrc-build # If the exit status indicates failure, set the wordlist empty to avoid # unrelated messages. local modules @@ -26,4 +26,4 @@ function _comp_kdesrc_run } ## Register autocomplete function -complete -o nospace -F _comp_kdesrc_run kdesrc-run +complete -o nospace -F _comp_kdesrc_build_run kdesrc-build diff --git a/doc/man-kdesrc-build.1.docbook b/doc/man-kdesrc-build.1.docbook index f97209c9..5483e425 100644 --- a/doc/man-kdesrc-build.1.docbook +++ b/doc/man-kdesrc-build.1.docbook @@ -623,7 +623,7 @@ Generate the &kdesrc-build; configuration file. <listitem> <para> Runs the program named by <replaceable>foo</replaceable> using - <command>kdesrc-build</command>'s normal build environment. All command + prefix.sh environment variables. All command line arguments present after this option are passed to <replaceable>foo</replaceable> as it is run. </para> diff --git a/doc/supported-cmdline-params.docbook b/doc/supported-cmdline-params.docbook index fb02d2d3..2a8014b6 100644 --- a/doc/supported-cmdline-params.docbook +++ b/doc/supported-cmdline-params.docbook @@ -59,31 +59,11 @@ a few). </varlistentry> <varlistentry id="cmdline-run"> -<term><option><link linkend="cmdline-run">--run</link></option> (or <option>--start-program</option>) <parameter>program [parameters ...]</parameter></term> +<term><option><link linkend="cmdline-run">--run</link></option> (or <option>--start-program</option>) [-e|--exec name] [-f|--fork] <parameter>program [parameters ...]</parameter></term> <listitem><para> This option interprets the next item on the command line as a program to run, -and &kdesrc-build; will then finish reading the configuration file, update the -environment as normal, and then execute the given program.</para> - -<para>This will not work to start a shell with the &kdesrc-build; environment -in most cases however, since interactive shells typically reset at least part -of the environment variables (such as <envar>PATH</envar> and -${install-dir}) in the startup sequence. -</para> - -<tip><para>If you want to see the environment used by &kdesrc-build;, you -can run the <command>printenv</command> command:</para> -<informalexample> -<screen>$ <command>kdesrc-build</command> <parameter>--run</parameter> <parameter>printenv</parameter> -KDE_SESSION_VERSION=4 -SDL_AUDIODRIVER=alsa -LANGUAGE= -XCURSOR_THEME=Oxygen_Blue -LESS=-R -M --shift 5 -QMAIL_CONTROLDIR=/var/qmail/control -... etc. -</screen> -</informalexample></tip> +and &kdesrc-build; will then finish reading the configuration file, source the +prefix.sh to apply environment variables, and then execute the given program.</para> </listitem> </varlistentry> diff --git a/kdesrc-run b/kdesrc-run deleted file mode 100755 index 90c55560..00000000 --- a/kdesrc-run +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env perl - -=pod - -=encoding UTF-8 - -=head1 NAME - -kdesrc-run - Run KDE applications built with kdesrc-build. - -=head1 SYNOPSIS - -kdesrc-run [options] <module-name> [arguments] - -=head1 OPTIONS - - -e, --exec <program> Specify program of the module. Default to module name. - -f, --fork Launch the program in a new session. - -q, --quiet Do not print run information. - -h, --help Print usage information and exit. - -=head1 EXAMPLES - -B<kdesrc-run -f kate -l 5 file1.txt> - - Launch kate in a new session with '-l 5 file1.txt' arguments. - -B<kdesrc-run -e kate-syntax-highlighter kate --list-themes> - - Launch kate-syntax-highlighter of module kate with '--list-themes' argument. - -=cut - -use 5.014; -use strict; -use warnings; -use autodie; - -use Pod::Usage; -use Getopt::Long qw(:config pass_through require_order); -use JSON::PP; -use List::Util qw(first); - -binmode STDOUT, 'encoding(UTF-8)'; -binmode STDERR, 'encoding(UTF-8)'; - -our $optExec; -our $optFork = 0; -our $optHelp = 0; -our $optQuiet = 0; - -GetOptions( - 'exec|e=s' => \$optExec, - 'fork|f' => \$optFork, - 'help|h' => sub { pod2usage(0); }, - 'quiet|q' => \$optQuiet, -); - -if ($#ARGV == -1) { - pod2usage(0); -} - -my $module = shift @ARGV; -my $exec = $optExec // $module; - -# According to XDG spec, if $XDG_STATE_HOME is not set, then we should default -# to ~/.local/state -my $xdgStateHome = $ENV{XDG_STATE_HOME} // "$ENV{HOME}/.local/state"; -my $dataFileName = "kdesrc-build-data"; -my @possibleDataPaths = ("./.$dataFileName", "$xdgStateHome/$dataFileName"); -my $buildDataFile = first { -e $_ } (@possibleDataPaths); - -if (not defined $buildDataFile) { - say qq("$dataFileName" file is not available. Exit now.); - exit 1; -} - -my $buildData = do { - open my $fh, '<', $buildDataFile; - local $/ = undef; - decode_json(<$fh>); -}; - -if (not defined $buildData->{$module}) { - say qq(Module "$module" has not been built yet.); - exit 1; -} - -my $buildDir = $buildData->{$module}{'build-dir'}; -my $installDir = $buildData->{$module}{'install-dir'}; -my $revision = $buildData->{$module}{'last-build-rev'}; -my $execPath = "$installDir/bin/$exec"; - -if (not -e $execPath) { - say qq(Program "$exec" does not exist.); - say qq(Try to set executable name with -e option.); - exit 127; # Command not found -} - -# Most of the logic is done by Perl, so the shell script here should be POSIX -# compliant. Consider using ShellCheck to make sure of that. -my $script = qq{ - #!/bin/sh - - # Set up environment variables (dot command). - . "$buildDir/prefix.sh"; - - # Launch the program with optional arguments. - if [ "$optFork" = 1 ]; then - setsid -f "$execPath" "\$@"; - else - "$execPath" "\$@"; - fi; -}; - -# Print run information -if (not $optQuiet) { - print '#' x 80, "\n"; - print ' ' x 35, 'kdesrc-run', "\n"; - say "Module: $module"; - say "Program: $exec"; - say "Revision: $revision"; - say "Arguments: @ARGV"; - print '#' x 80, "\n"; - print "\n"; -} - -# Instead of embedding @ARGV in shell script with string interpolation, pass -# them as arguments of the script. Let the shell handle the list through "$@", -# so it will do the quoting on each one of them. -# -# Run the script with sh options specification: -# sh -c command_string command_name $1 $2 $3... -exec('/bin/sh', '-c', $script, $exec, @ARGV); diff --git a/modules/ksb/Application.pm b/modules/ksb/Application.pm index 952f3f8f..fd17662f 100644 --- a/modules/ksb/Application.pm +++ b/modules/ksb/Application.pm @@ -38,6 +38,7 @@ use ksb::ModuleSet 0.20; use ksb::ModuleSet::KDEProjects; use ksb::ModuleSet::Qt; use ksb::RecursiveFH; +use ksb::StartProgram; use ksb::TaskManager; use ksb::Updater::Git; use ksb::Util; @@ -324,13 +325,8 @@ EOF # For user convenience, cmdline ignored selectors would not override the config selectors. Instead, they will be merged. my %ignoredSelectors = (%ignored_in_cmdline, %ignored_in_global_section); - # Check if we're supposed to drop into an interactive shell instead. If so, - # here's the stop off point. - if (@startProgramAndArgs) { - $ctx->setupEnvironment(); # Read options from set-env - $ctx->commitEnvironmentChanges(); # Apply env options to environment - _executeCommandLineProgram(@startProgramAndArgs); # noreturn + StartProgram::executeCommandLineProgram($ctx, @startProgramAndArgs); # noreturn } if (!isTesting()) { @@ -1198,40 +1194,6 @@ sub _readConfigurationOptions ($ctx, $fh, $cmdlineGlobalOptions, $deferredOption return @module_list; } -# Exits out of kdesrc-build, executing the user's preferred shell instead. The -# difference is that the environment variables should be as set in kdesrc-build -# instead of as read from .bashrc and friends. -# -# You should pass in the options to run the program with as a list. -# -# Meant to implement the --run command line option. -sub _executeCommandLineProgram -{ - my ($program, @args) = @_; - - if (!$program) - { - error ("You need to specify a program with the --run option."); - exit 1; # Can't use finish here. - } - - if (($< != $>) && ($> == 0)) - { - error ("kdesrc-build will not run a program as root unless you really are root."); - exit 1; - } - - debug ("Executing b[r[$program] ", join(' ', @args)); - - exit 0 if pretending(); - - exec $program, @args or do { - # If we get to here, that sucks, but don't continue. - error ("Error executing $program: $!"); - exit 1; - }; -} - # Function: _handle_install # # Handles the installation process. Simply calls 'make install' in the build diff --git a/modules/ksb/Cmdline.pm b/modules/ksb/Cmdline.pm index 2950c890..cb1666e4 100644 --- a/modules/ksb/Cmdline.pm +++ b/modules/ksb/Cmdline.pm @@ -232,7 +232,6 @@ sub readCommandLineOptionsAndSelectors (@options) # Getopt::Long doesn't set these up for us even though we specify an # array. Set them up ourselves. - 'start-program' => [ ], 'ignore-modules' => [ ], # Module selectors, the <> is Getopt::Long shortcut for an @@ -256,6 +255,26 @@ sub readCommandLineOptionsAndSelectors (@options) # build options for Getopt::Long my @supportedOptions = _supportedOptions(); + # If we have --run option, grab all the rest arguments to pass to the corresponding parser. + # This way the arguments after --run could start with "-" or "--". + my $run_index = -1; + foreach my $i (0 .. $#options) { + if ($options[$i] eq "--run" or $options[$i] eq "--start-program") { + $run_index = $i; + last; + } + } + + if ($run_index != -1) { + @{ $opts->{"start-program"} } = @options[$run_index+1 .. $#options]; + @options = @options[0 .. $run_index-1]; # remove all after --run, and the --run itself + + if (! @{ $opts->{"start-program"} }){ # check this here, because later the empty list will be treated as not wanting to start program + error ("You need to specify a module with the --run option"); + exit 1; # Do not continue + } + } + # Actually read the options. my $optsSuccess = GetOptionsFromArray(\@options, \%foundOptions, # Options here should not duplicate the flags and options defined below @@ -269,9 +288,8 @@ sub readCommandLineOptionsAndSelectors (@options) croak_runtime("Error reading command-line options."); } - # Don't get ignore-modules and start-program (i.e. --run) confused with - # global options - my @protectedKeys = ('ignore-modules', 'start-program'); + # Don't get ignore-modules confused with global options + my @protectedKeys = ('ignore-modules'); @{$opts}{@protectedKeys} = @foundOptions{@protectedKeys}; delete @foundOptions{@protectedKeys}; @@ -438,7 +456,6 @@ sub _supportedOptions 'set-module-option-value=s', 'show-info', 'show-options-specifiers', - 'start-program|run=s{,}', 'stop-after|to=s', 'stop-before|until=s', 'version|v', diff --git a/modules/ksb/StartProgram.pm b/modules/ksb/StartProgram.pm new file mode 100644 index 00000000..9e97b5a4 --- /dev/null +++ b/modules/ksb/StartProgram.pm @@ -0,0 +1,122 @@ +package StartProgram; + +use ksb; +use ksb::Debug; + +=pod + +=encoding UTF-8 + +=head1 SYNOPSIS + +kdesrc-build --run [options] <module-name> [arguments] + +=head1 OPTIONS + + -e, --exec <program> Specify program of the module. Default to module name. + -f, --fork Launch the program in a new session. + +=head1 EXAMPLES + +B<kdesrc-build --run -f kate -l 5 file1.txt> + + Launch kate in a new session with '-l 5 file1.txt' arguments. + +B<kdesrc-build --run -e kate-syntax-highlighter kate --list-themes> + + Launch kate-syntax-highlighter of module kate with '--list-themes' argument. + +=cut + +sub executeCommandLineProgram +{ + my ($ctx, @args) = @_; + + my $optExec = undef; + my $optFork = 0; + + # We cannot use GetOptionsFromArray here, because -e or -f could be meant to be arguments of module executable. But that would steal them. + # We manually care of them, they can only appear in front of module/executable name. + my $arg; + while ($arg = shift @args) { + if ($arg eq "-f" || $arg eq "--fork") { + $optFork = 1; + next; + } elsif ($arg eq "-e" || $arg eq "--exec") { + $optExec = shift @args; + if (not defined $optExec){ + error("-e option requires a name of executable"); + exit(1) + } + next; + } + last; + } + + my $module = $arg; + if (not defined $module) { # the case when user specified -e executable_name and/or -f, but then did not specified the module name + error("The module name is missing"); + exit 1; + } + my $executable = $optExec // $module; + my $buildData = $ctx->{persistent_options}; + + if (not defined $buildData->{$module}) { + say qq(Module "$module" has not been built yet.); + exit 1; + } + + my $buildDir = $buildData->{$module}{'build-dir'}; + my $installDir = $buildData->{$module}{'install-dir'}; + my $revision = $buildData->{$module}{'last-build-rev'}; + my $execPath = "$installDir/bin/$executable"; + + if (not -e $execPath) { + say qq(Executable "$executable" does not exist.); + say qq(Try to set executable name with -e option.); + exit 127; # Command not found + } + + # Most of the logic is done by Perl, so the shell script here should be POSIX + # compliant. Consider using ShellCheck to make sure of that. + my $script = <<~EOF; + #!/bin/sh + + # Set up environment variables (dot command). + . "$buildDir/prefix.sh" + + # Launch the program with optional arguments. + if [ "$optFork" = 1 ]; then + setsid -f "$execPath" \$@ + else + "$execPath" \$@ + fi + EOF + + # Print run information + note ( + "#" x 80, "\n", + "Module: $module\n", + "Executable: $executable\n", + "Revision: $revision\n", + "Arguments: @args\n", + "#" x 80, "\n", + "\n" + ); + + exit 0 if pretending(); + + # Instead of embedding @args in shell script with string interpolation, pass + # them as arguments of the script. Let the shell handle the list through "$@", + # so it will do the quoting on each one of them. + # + # Run the script with sh options specification: + # sh -c command_string command_name $1 $2 $3... + exec('/bin/sh', '-c', $script, "kdesrc-build run script", @args) or do { + # If we get to here, that sucks, but don't continue. + error ("Error executing $executable: $!"); + exit 1; + }; +} + +1; diff --git a/modules/ksb/TaskManager.pm b/modules/ksb/TaskManager.pm index b97269b8..765fcf4c 100644 --- a/modules/ksb/TaskManager.pm +++ b/modules/ksb/TaskManager.pm @@ -153,7 +153,7 @@ sub _handle_updates ($ipc, $ctx) # running ->update() from short-circuiting if an error is noted. $hadError = !$module->update($ipc, $ctx) || $hadError; - # Cache module directories, e.g. to be consumed in kdesrc-run + # Cache module directories, e.g. to be consumed in kdesrc-build --run # This is needed for --no-async mode where the buildSingleModule won't run # But the other one is needed for --async mode since persistent options # only work from within the build process @@ -173,7 +173,7 @@ sub _buildSingleModule ($ipc, $ctx, $module, $startTimeRef) $ctx->resetEnvironment(); $module->setupEnvironment(); - # Cache module directories, e.g. to be consumed in kdesrc-run + # Cache module directories, e.g. to be consumed in kdesrc-build --run $module->setPersistentOption('source-dir', $module->fullpath('source')); $module->setPersistentOption('build-dir', $module->fullpath('build')); $module->setPersistentOption('install-dir', $module->installationPath()); diff --git a/scripts/gen_zsh_completions.py b/scripts/gen_zsh_completions.py index 64a392c5..7895130c 100644 --- a/scripts/gen_zsh_completions.py +++ b/scripts/gen_zsh_completions.py @@ -178,7 +178,7 @@ short_descriptions = { # contains one of the options (any of them) from set, an "--resume": "Resume after a build failure", "--resume-from": "Skips modules until just before or after the given package, then operates as normal", "--revision": "Checkout a specific numbered revision", - "--run": "A program to run with kdesrc-build", + # "--run": "A program to run with kdesrc-build", # Todo Needs to be added separately "--run-tests": "Built the modules with support for running their test suite", "--set-module-option-value": "Override an option in your configuration file for a specific module", "--source-dir": "Directory that stores the KDE sources",