Files
core/autogen.sh
Christian Lohmaier 037de86626 improve builddir!=srcdir detection with case-preserving filesystems
on Windows and macOS autogen.sh could misdetect the build directory as
being different from the source directory if the filesystem is
case-preserving but not case-sensitive. e.g.

cd ~/BuildDir ; ~/builddir/autogen.sh

It is the same directory, but treated as a different one and thus
autogen would create the module/Makefile files and also a link to the
include directory. That however then ends up being a include/include
link and that then fails the skia build.

So use the same method to get both paths to avoid the problem.
Change from cwd() to getcwd() since despite the documentation saying it
would be the same, getcwd is actually returning the actual name as
stored in the filesystem. Also use the module's chdir so that the PWD
environment variable doesn't need to be set manually.

Change-Id: I705dc584a91be9f63052bd1f72d4a0c4ba73f3ec
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187536
Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
Tested-by: Jenkins
2025-07-09 11:21:51 +02:00

351 lines
12 KiB
Bash
Executable File

:
#
# This script checks various configure parameters and uses three files:
# * autogen.input (ro)
# * autogen.lastrun (rw)
# * autogen.lastrun.bak (rw)
#
# If _no_ parameters:
# Read args from autogen.input or autogen.lastrun
# Else
# Backup autogen.lastrun as autogen.lastrun.bak
# Write autogen.lastrun with new commandline args
#
# Run configure with checked args
#
eval 'exec perl -S $0 ${1+"$@"}'
if 0;
use strict;
# use Cwd's chdir to also set PWD environment variable
use Cwd ('chdir', 'getcwd', 'realpath');
use File::Basename;
my $src_path=dirname(realpath($0));
my $build_path=realpath(getcwd());
# workaround for case-preserving filesystems to get the canonical name
# otherwise the src_path may be different from the build_path by case only
# and mess up the builddir != srcdir handling
chdir($src_path);
$src_path=getcwd();
# since this looks crazy, if you have a symlink on a path up to and including
# the current directory, we need our configure to run in the realpath of that
# such that compiled (realpath'd) dependency filenames match the filenames
# used in our makefiles - ie. this gets dependencies right via SRC_ROOT
chdir ($build_path);
my $aclocal;
my $autoconf;
# check we have various vital tools
sub sanity_checks($)
{
my $system = shift;
my @path = split (':', $ENV{'PATH'});
my %required =
(
'pkg-config' => "pkg-config is required to be installed",
$autoconf => "autoconf is required",
$aclocal => "$aclocal is required",
);
if ($ENV{WSL_DISTRO_NAME} && $ENV{PATH} =~ /mingw64/) {
# for wsl-as-helper build we only need the m4 macros like for macOS
delete $required{'pkg-config'};
}
for my $elem (@path) {
for my $app (keys %required) {
if (-f "$elem/$app") {
delete $required{$app};
}
}
}
if ((keys %required) > 0) {
print ("Various low-level dependencies are missing, please install them:\n");
for my $app (keys %required) {
print "\t $app: " . $required{$app} . "\n";
}
exit (1);
}
}
# one argument per line
sub read_args($)
{
my $file = shift;
my $fh;
my @lst;
open ($fh, $file) || die "can't open file: $file";
while (<$fh>) {
chomp();
s/^\s+//;
s/\s+$//;
# migrate from the old system
if ( substr($_, 0, 1) eq "'" ) {
print STDERR "Migrating options from the old autogen.lastrun format, using:\n";
my @opts;
@opts = split(/'/);
foreach my $opt (@opts) {
if ( substr($opt, 0, 1) eq "-" ) {
push @lst, $opt;
print STDERR " $opt\n";
}
}
} elsif ( /^INCLUDE:(.*)/ ) {
# include another .conf into this one
my $config = "$src_path/distro-configs/$1.conf";
if (! -f $config) {
invalid_distro ($config, $1);
}
push @lst, read_args ($config);
} elsif ( substr($_, 0, 1) eq "#" ) {
# comment
} elsif ( length == 0 ) {
# empty line
} else {
push @lst, $_;
}
}
close ($fh);
# print "read args from file '$file': @lst\n";
return @lst;
}
sub show_distro_configs($$)
{
my ($prefix, $path) = @_;
my $dirh;
opendir ($dirh, "$path");
while (($_ = readdir ($dirh))) {
if (-d "$path/$_") {
show_distro_configs(
$prefix eq "" ? "$_/" : "$prefix/$_/", "$path/$_")
unless $_ eq '.' || $_ eq '..';
next;
}
/(.*)\.conf$/ || next;
print STDERR "\t$prefix$1\n";
}
closedir ($dirh);
}
sub invalid_distro($$)
{
my ($config, $distro) = @_;
print STDERR "Can't find distro option set: $config\n";
print STDERR "Distros with distro option sets are:\n";
show_distro_configs("", "$src_path/distro-configs");
exit (1);
}
# Avoid confusing "aclocal: error: non-option arguments are not accepted: '.../m4'." error message.
die "\$src_path must not contain spaces, but it is '$src_path'." if ($src_path =~ / /);
# Alloc $ACLOCAL to specify which aclocal to use
$aclocal = $ENV{ACLOCAL} ? $ENV{ACLOCAL} : 'aclocal';
# Alloc $AUTOCONF to specify which autoconf to use
# (e.g. autoconf268 from a backports repo)
$autoconf = $ENV{AUTOCONF} ? $ENV{AUTOCONF} : 'autoconf';
my $system = `uname -s`;
chomp $system;
sanity_checks ($system) unless($system eq 'Darwin');
# If we are running in a LODE env, make sure we find the right aclocal
# by making sure that LODE_HOME/opt/bin is in the PATH
if (defined $ENV{LODE_HOME})
{
my $lode_path = quotemeta "$ENV{LODE_HOME}/opt/bin";
if($ENV{PATH} !~ $lode_path)
{
$ENV{PATH}="$ENV{LODE_HOME}/opt/bin:$ENV{PATH}";
print STDERR "add LODE_HOME/opt/bin in PATH\n";
}
}
my $aclocal_flags = $ENV{ACLOCAL_FLAGS};
$aclocal_flags .= " -I $src_path/m4";
# the m4/mac directory provides the pkg-config macros used in configure
$aclocal_flags .= " -I $src_path/m4/mac" if ($system eq 'Darwin' || ($ENV{WSL_DISTRO_NAME} && $ENV{PATH} =~ /mingw64/));
$ENV{AUTOMAKE_EXTRA_FLAGS} = '--warnings=no-portability' if (!($system eq 'Darwin'));
if ($src_path ne $build_path)
{
system ("ln -sf $src_path/configure.ac configure.ac");
system ("ln -sf $src_path/g g");
my $src_path_win=$src_path;
if ($system =~ /CYGWIN.*/) {
$src_path_win=`cygpath -m $src_path`;
chomp $src_path_win;
}
# wsl-as-helper method: autogen.sh/configure runs within a wsl-container (WSL_DISTRO_NAME)
# and build is run from within git-bash (that adds .../Git/mingw64/bin to PATH)
if ($ENV{WSL_DISTRO_NAME} && $ENV{PATH} =~ /mingw64/) {
$src_path_win=`wslpath -m $src_path`;
chomp $src_path_win;
}
my @modules = <$src_path/*/Makefile>;
foreach my $module (@modules)
{
my $dir = basename (dirname ($module));
mkdir ($dir);
system ("rm -f $dir/Makefile");
system ("printf 'module_directory:=$src_path_win/$dir/\ninclude \$(module_directory)/../solenv/gbuild/partial_build.mk\n' > $dir/Makefile");
}
my @external_modules = <$src_path/external/*/Makefile>;
mkdir ("external");
system ("ln -sf $src_path/external/Module_external.mk external/");
foreach my $module (@external_modules)
{
my $dir = basename (dirname ($module));
mkdir ("external/$dir");
system ("rm -f external/$dir/Makefile");
system ("printf 'module_directory:=$src_path_win/external/$dir/\ninclude \$(module_directory)/../../solenv/gbuild/partial_build.mk\n' > external/$dir/Makefile");
}
}
system ("$aclocal $aclocal_flags") && die "Failed to run aclocal";
unlink ("configure");
system ("$autoconf -I ${src_path}") && die "Failed to run autoconf";
die "Failed to generate the configure script" if (! -f "configure");
# Handle help arguments first, so we don't clobber autogen.lastrun
for my $arg (@ARGV) {
if ($arg =~ /^(--help|-h|-\?)$/) {
print STDOUT "autogen.sh - libreoffice configuration helper\n";
print STDOUT "When called without arguments, arguments from autogen.input are used.\n";
print STDOUT "\nArguments processed in the helper:\n";
print STDOUT " --with-distro use a config from distro-configs/\n";
print STDOUT " the name needs to be passed without extension\n";
print STDOUT " --best-effort don't fail on un-known configure with/enable options\n";
print STDOUT "\nOther arguments passed directly to configure:\n\n";
system ("./configure --help");
exit;
}
}
my @cmdline_args = ();
my $input = "autogen.input";
my $lastrun = "autogen.lastrun";
if (!@ARGV) {
if (-f $input) {
if (-f $lastrun) {
print STDERR <<WARNING;
********************************************************************
*
* Reading $input and ignoring $lastrun!
* Consider removing $lastrun to get rid of this warning.
*
********************************************************************
WARNING
}
@cmdline_args = read_args ($input);
} elsif (-f $lastrun) {
print STDERR "Reading $lastrun. Please rename it to $input to avoid this message.\n";
@cmdline_args = read_args ($lastrun);
}
} else {
if (-f $input) {
print STDERR <<WARNING;
********************************************************************
*
* Using commandline arguments and ignoring $input!
*
********************************************************************
WARNING
}
@cmdline_args = @ARGV;
}
my @args;
my $default_config = "$src_path/distro-configs/default.conf";
my $option_checking = 'fatal';
if (-f $default_config) {
print STDERR "Reading default config file: $default_config.\n";
push @args, read_args ($default_config);
}
for my $arg (@cmdline_args) {
if ($arg =~ m/--with-distro=(.*)$/) {
my $config = "$src_path/distro-configs/$1.conf";
if (! -f $config) {
invalid_distro ($config, $1);
}
push @args, read_args ($config);
} elsif ($arg =~ m/--best-effort$/) {
$option_checking = 'warn';
} else {
push @args, $arg;
}
}
if (defined $ENV{NOCONFIGURE}) {
print "Skipping configure process.";
} else {
# Save autogen.lastrun only if we did get some arguments on the command-line
if (! -f $input && @ARGV) {
if (scalar(@cmdline_args) > 0) {
# if there's already an autogen.lastrun, make a backup first
if (-e $lastrun) {
open (my $fh, $lastrun) || warn "Can't open $lastrun.\n";
open (BAK, ">$lastrun.bak") || warn "Can't create backup file $lastrun.bak.\n";
while (<$fh>) {
print BAK;
}
close (BAK) && close ($fh);
}
# print "Saving command-line args to $lastrun\n";
my $fh;
open ($fh, ">autogen.lastrun") || die "Can't open autogen.lastrun: $!";
for my $arg (@cmdline_args) {
print $fh "$arg\n";
}
close ($fh);
}
}
push @args, "--srcdir=$src_path";
push @args, "--enable-option-checking=$option_checking";
# When running a shell script from Perl on WSL, weirdly named
# environment variables like the "ProgramFiles(x86)" one don't get
# imported by the shell. So export it as PROGRAMFILESX86 instead.
my $building_for_linux = 0;
my $building_with_emscripten = 0;
foreach my $arg (@args) {
$building_for_linux = 1 if ($arg =~ /--host=x86_64.*linux/);
$building_with_emscripten = 1 if ($arg =~ /^--host=wasm.*-emscripten$/);
}
unshift @args, "./configure";
unshift @args, "emconfigure" if ($building_with_emscripten);
print "Running '" . join (" ", @args), "'\n";
if (`wslsys 2>/dev/null` ne "" && !$building_for_linux) {
if (!$ENV{"ProgramFiles(x86)"}) {
print STDERR "To build for Windows on WSL, you need to set the WSLENV environment variable in the Control Panel to 'ProgramFiles(x86)'\n";
print STDERR "If you actually do want to build for WSL (Linux) on WSL, pass a --host=x86_64-pc-linux-gnu option\n";
exit (1);
}
$ENV{"PROGRAMFILESX86"} = $ENV{"ProgramFiles(x86)"};
}
system (@args) && die "Error running configure";
}
# cspell:ignore Distros PROGRAMFILESX WSLENV emconfigure realpath wslsys
# Local Variables:
# mode: perl
# cperl-indent-level: 4
# tab-width: 4
# indent-tabs-mode: nil
# End:
# vim:set ft=perl shiftwidth=4 softtabstop=4 expandtab: #