You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
12 KiB
449 lines
12 KiB
#!/usr/bin/env perl |
|
|
|
# Script to create a configuration file for kdesrc-build. |
|
# |
|
# Copyright © 2011, 2016 Michael Pyne. <mpyne@kde.org> |
|
# Home page: https://kdesrc-build.kde.org/ |
|
# |
|
# This program is free software; you can redistribute it and/or modify it under |
|
# the terms of the GNU General Public License as published by the Free Software |
|
# Foundation; either version 2 of the License, or (at your option) any later |
|
# version. |
|
# |
|
# This program is distributed in the hope that it will be useful, but WITHOUT |
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
|
# details. |
|
# |
|
# You should have received a copy of the GNU General Public License along with |
|
# this program; if not, write to the Free Software Foundation, Inc., 51 |
|
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
|
|
use strict; |
|
use 5.018; |
|
use IO::Pipe; |
|
use File::Copy; |
|
use File::Temp qw/tempfile/; |
|
use File::Basename; |
|
use Cwd qw(abs_path); |
|
|
|
our $VERSION = 0.03; # Not user-visible yet. |
|
|
|
sub clearScreen |
|
{ |
|
require POSIX; |
|
my $termios = POSIX::Termios->new(); |
|
$termios->getattr(1); # Get STDOUT attributes |
|
|
|
require Term::Cap; |
|
my $terminal = Term::Cap->Tgetent({OSPEED => $termios->getospeed}); |
|
|
|
# Force the clear characters to be output immediately. |
|
# Otherwise it might overlap with other output, like error messages. |
|
local $| = 1; |
|
|
|
print $terminal->Tputs('cl', 0); |
|
|
|
return 0; |
|
} |
|
|
|
sub runDialogExecutable |
|
{ |
|
my (@args) = @_; |
|
|
|
# Allow for 2 more file descriptors (on top of the normally allowed 0, 1, |
|
# 2) to survive the upcoming exec |
|
# See "SYSTEM_FD_MAX" in perldoc:perlvar |
|
$^F = 4; |
|
|
|
my $pipe = new IO::Pipe; |
|
my $pid; |
|
|
|
if ($pid = fork()) { |
|
# Parent |
|
$pipe->reader(); |
|
|
|
my $output = <$pipe>; |
|
|
|
waitpid $pid, 0; |
|
my $result = ($? >> 8); |
|
$pipe->close(); |
|
|
|
# dialog uses -1 as an exit code, Perl gets just the standard 8 bits |
|
# the rest of UNIX uses... |
|
if ($? == -1) { |
|
clearScreen(); |
|
die "Failed to run dialog(1): $@"; |
|
} |
|
elsif ($result == 255) { |
|
clearScreen(); |
|
die "Canceled the dialog"; |
|
} |
|
return $output || $result; |
|
} |
|
elsif (defined $pid) { |
|
# Child |
|
$pipe->writer(); |
|
my $outputFd = $pipe->fileno(); |
|
|
|
print "Using fd $outputFd"; |
|
exec ('dialog', '--output-fd', $outputFd, |
|
'--backtitle', 'kdesrc-build setup', |
|
@args); |
|
} |
|
else { |
|
die "Unable to fork? $!"; |
|
} |
|
} |
|
|
|
sub getUserInput |
|
{ |
|
my $prompt = shift; |
|
my $default = shift; |
|
|
|
my @args = qw/--inputbox 8 50/; |
|
splice @args, 1, 0, $prompt; |
|
push @args, $default if $default; |
|
|
|
return runDialogExecutable(@args); |
|
} |
|
|
|
sub getMenuOption |
|
{ |
|
my ($prompt, @opts) = @_; |
|
@opts = @{$opts[0]} if ref $opts[0] eq 'ARRAY'; |
|
|
|
my @args = qw/--menu 20 70 18/; |
|
splice @args, 1, 0, $prompt; |
|
|
|
while(my ($k, $v) = splice (@opts, 0, 2)) { |
|
push @args, $k, $v; |
|
} |
|
|
|
return runDialogExecutable(@args); |
|
} |
|
|
|
sub showInfo |
|
{ |
|
my $message = shift; |
|
my @args = qw/--msgbox 20 62/; |
|
splice @args, 1, 0, $message; |
|
|
|
return runDialogExecutable(@args); |
|
} |
|
|
|
sub getYesNoAnswer |
|
{ |
|
my $prompt = shift; |
|
my @args = qw/--yesno 8 55/; |
|
splice @args, 1, 0, $prompt; |
|
|
|
return runDialogExecutable(@args) == 0; |
|
} |
|
|
|
sub getDirectory |
|
{ |
|
my $dir = shift; |
|
my @args = qw/--dselect 10 70/; |
|
splice @args, 1, 0, $dir; |
|
|
|
return runDialogExecutable(@args); |
|
} |
|
|
|
sub getListOptions |
|
{ |
|
my ($prompt, $opts, $enabled) = @_; |
|
die "\$opts not a hash ref" unless (ref $opts eq 'ARRAY'); |
|
die "\$enabled not a hash ref" unless (ref $enabled eq 'HASH'); |
|
|
|
my @args = qw/--checklist 20 70 18/; |
|
splice @args, 1, 0, $prompt; |
|
splice @args, 0, 0, '--output-separator', ','; |
|
|
|
while (my ($k, $v) = splice(@{$opts}, 0, 2)) { |
|
push (@args, $k, $v, (exists ${$enabled}{$k} ? 'on' : 'off')); |
|
} |
|
|
|
my $output = runDialogExecutable(@args); |
|
|
|
# Filter out empty results, remove quotes. |
|
my @items = split (/,/, $output); |
|
s/^"(.*)"$/\1/ foreach @items; |
|
@items = grep { length $_ } @items; |
|
return @items; |
|
} |
|
|
|
# The 'dialog(1)' program is required, verify it exists before going |
|
# further. |
|
# We use the --help option since it doesn't send weird terminal characters to the screen |
|
# and it's supported on dialog and Debian's dialog replacement called whiptail. |
|
system('dialog', '--help') == 0 or do { |
|
my $osError = "$!"; |
|
|
|
say "Unable to run the dialog(1) program, it is required for this setup script."; |
|
if ($? == -1) { |
|
say "\tThe program wouldn't even run, due to error: $osError"; |
|
} |
|
else { |
|
say "\tProgram ran, but exited with error: ", $? >> 8; |
|
} |
|
|
|
exit 1; |
|
}; |
|
|
|
showInfo(<<EOF); |
|
This program sets up a base kdesrc-build configuration to |
|
use. |
|
|
|
It can be modified as you wish later. Before the form is |
|
presented, you will be asked if you would like an |
|
explanation of the kdesrc-build file layout. It is |
|
recommended to read this if you are not already familiar |
|
with building software. |
|
EOF |
|
|
|
if (getYesNoAnswer('See the tutorial?')) { |
|
showInfo(<<EOF); |
|
kdesrc-build must download source code from the KDE |
|
repositories. This source code is then compiled, in the |
|
"build directory". Once complete, this compiled code is |
|
installed to its final location, the "install directory". |
|
|
|
This program will only configure the install location, but |
|
all directories are configurable. |
|
|
|
The space requirements vary with the amount of software you choose |
|
to build, and whether you keep the build directories to speed up |
|
later builds. You will probably need at least 20 GiB in total free |
|
space unless you take steps to customize your install to use fewer |
|
modules. |
|
EOF |
|
} |
|
|
|
# If the user appears to be using a proxy, ask for it directly, otherwise |
|
# prompt for one. |
|
my $proxy = $ENV{http_proxy} // ''; |
|
|
|
my $installDir = getMenuOption('Where do you want to install the software?', |
|
[ |
|
home => "$ENV{HOME}/kde/usr (default)", |
|
custom => "Custom location, chosen next screen", |
|
]); |
|
|
|
if ($installDir eq 'custom') { |
|
$installDir = getDirectory('/usr/local/kde'); |
|
} |
|
else { |
|
$installDir = "~/kde/usr"; |
|
} |
|
|
|
my @chosenModules = getListOptions( |
|
"Which major module groups do you want to build?", |
|
[ |
|
frameworks => 'KDE Frameworks 5 - Essential libraries/runtime (required)', |
|
workspace => 'KDE Plasma 5 Desktop and workspace', |
|
base => 'Assorted useful KF5-based applications', |
|
pim => 'Personal Information Management software', |
|
], |
|
{ |
|
frameworks => 1, |
|
workspace => 1, |
|
base => 1, |
|
}, |
|
); |
|
|
|
my $numCpus = getUserInput( |
|
'How many CPU cores do you wish to use for building?', '4'); |
|
|
|
my $outputFileName = "$ENV{HOME}/.kdesrc-buildrc"; |
|
my $output; # Will be output filehandle. |
|
|
|
while (-e $outputFileName) { |
|
(my $printableName = $outputFileName) =~ s/^$ENV{HOME}/~/; |
|
my $outputChoice = getMenuOption( |
|
"$printableName already exists, what do you want to do?", |
|
[ |
|
backup => 'Make a backup, then overwrite with the new configuration', |
|
custom => 'Write the new configuration to a different file', |
|
cancel => 'Cancel setup', |
|
], |
|
); |
|
|
|
if ($outputChoice eq 'cancel') { |
|
showInfo('Setup canceled'); |
|
exit 0; |
|
} |
|
|
|
if ($outputChoice eq 'custom') { |
|
$outputFileName = getUserInput('Enter desired configuration file name.'); |
|
$outputFileName =~ s/^~/$ENV{HOME}/; |
|
} |
|
|
|
if ($outputChoice eq 'backup') { |
|
|
|
copy($outputFileName, "$outputFileName~") or do { |
|
my $error = "$!"; |
|
showInfo(<<EOF); |
|
Failed to make backup of $outputFileName, due to error $error. |
|
Configuration will be written to a temporary file instead. |
|
EOF |
|
|
|
($output, $outputFileName) = tempfile("kdesrc-buildrc-XXXX"); |
|
}; |
|
|
|
last; |
|
} |
|
} |
|
|
|
# Filehandle could already be opened as a tempfile. |
|
if (!$output) { |
|
open ($output, '>', $outputFileName) or do { |
|
my $error = "$!"; |
|
showInfo (<<EOF); |
|
Unable to open output file $outputFileName for writing due to error $error. |
|
EOF |
|
die "$!"; |
|
} |
|
} |
|
|
|
print $output <<EOF; |
|
# Autogenerated by kdesrc-build-setup. You may modify this file if desired. |
|
global |
|
|
|
EOF |
|
|
|
print $output <<EOF; |
|
# This option is used to switch development tracks for many modules at |
|
# once. 'kf5-qt5' is the latest KF5 and Qt5-based software. |
|
branch-group kf5-qt5 |
|
|
|
# The path to your Qt installation (default is empty, assumes Qt provided |
|
# by system) |
|
# qtdir ~/qt5 |
|
|
|
# Finds and includes *KDE*-based dependencies into the build. This makes |
|
# it easier to ensure that you have all the modules needed, but the |
|
# dependencies are not very fine-grained so this can result in quite a few |
|
# modules being installed that you didn't need. |
|
include-dependencies true |
|
|
|
# Install directory for KDE software |
|
kdedir $installDir |
|
|
|
# Directory for downloaded source code |
|
source-dir ~/kde/src |
|
|
|
# Directory to build KDE into before installing |
|
# relative to source-dir by default |
|
build-dir ~/kde/build |
|
|
|
# Use multiple cores for building. Other options to GNU make may also be |
|
# set. |
|
make-options -j$numCpus |
|
|
|
# kdesrc-build can install a sample .xsession file for "Custom" |
|
# (or "XSession") logins, |
|
install-session-driver false |
|
|
|
# or add a environment variable-setting script to |
|
# ~/.config/kde-env-master.sh |
|
install-environment-driver true |
|
EOF |
|
|
|
if ($proxy) { |
|
print $output <<EOF; |
|
|
|
# Proxy to use for HTTP downloads. |
|
http-proxy $proxy |
|
|
|
# Prefer HTTPS instead of Git-native protocol for git modules that come |
|
# from 'kde-projects' repositories. |
|
# |
|
# Note that any git:// repositories you use will need to be |
|
# manually converted to https:// URLs if your network does not allow |
|
# git:// protcol. |
|
git-desired-protocol https # http is also valid |
|
EOF |
|
} |
|
|
|
print $output <<EOF; |
|
end global |
|
|
|
EOF |
|
|
|
# Assume we can refer to files present alongside kdesrc-build in the source |
|
# directory |
|
my $basedir = dirname(abs_path($0)); |
|
if (! -e "$basedir/kf5-frameworks-build-include") { |
|
# Check if it's installed to a share/ prefix |
|
$basedir = abs_path(dirname($0) . "/../share/kdesrc-build/"); |
|
|
|
if (! -e "$basedir/kf5-frameworks-build-include") { |
|
close $output; |
|
showInfo("Unable to find kdesrc-build installation to build a configuration!"); |
|
exit 1; |
|
} |
|
} |
|
|
|
if (grep /^frameworks$/, @chosenModules) { |
|
print $output <<EOF; |
|
|
|
# Refers to the kf5-frameworks file included as part of kdesrc-build. The file |
|
# is simply read-in at this point as if you'd typed it in yourself. |
|
include $basedir/kf5-frameworks-build-include |
|
|
|
EOF |
|
} |
|
|
|
if (grep /^workspace$/, @chosenModules) { |
|
print $output <<EOF; |
|
|
|
# Refers to the kf5-workspace file included as part of kdesrc-build. The file |
|
# is simply read-in at this point as if you'd typed it in yourself. |
|
include $basedir/kf5-workspace-build-include |
|
|
|
EOF |
|
} |
|
|
|
if (grep /^base$/, @chosenModules) { |
|
print $output <<EOF; |
|
|
|
# Refers to the kf5-applications file included as part of kdesrc-build. The file |
|
# is simply read-in at this point as if you'd typed it in yourself. |
|
include $basedir/kf5-applications-build-include |
|
|
|
EOF |
|
} |
|
|
|
if (grep /^pim$/, @chosenModules) { |
|
print $output <<EOF; |
|
|
|
# Refers to the kf5-kdepim file included as part of kdesrc-build. The file |
|
# is simply read-in at this point as if you'd typed it in yourself. |
|
include $basedir/kf5-kdepim-build-include |
|
|
|
EOF |
|
} |
|
|
|
close($output); |
|
$outputFileName =~ s/^$ENV{HOME}/~/; |
|
showInfo("Generated configuration has been written to $outputFileName"); |
|
|
|
# Say same thing in text mode just in case. |
|
system('clear'); |
|
say "Generated configuration has been written to $outputFileName"; |
|
|
|
if ($outputFileName ne '~/.kdesrc-buildrc') { |
|
say <<EOF; |
|
|
|
Note that your configuration file in $outputFileName will |
|
NOT BE USED unless you either: |
|
1. Overwrite your ~/.kdesrc-buildrc with $outputFileName, or |
|
2. Copy $outputFileName to be called 'kdesrc-buildrc' in some directory |
|
and ALWAYS run kdesrc-build from the directory, or |
|
3. ALWAYS pass the "--rc-file $outputFileName" option to kdesrc-build when you |
|
run it. |
|
EOF |
|
} |
|
|
|
exit 0;
|
|
|