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

#!/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;