#!/usr/bin/perl
#
#  Copyright (c) 1997-2022
#  Ewgenij Gawrilow, Michael Joswig, and the polymake team
#  Technische Universität Berlin, Germany
#  https://polymake.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, or (at your option) any
#  later version: http://www.gnu.org/licenses/gpl.txt.
#
#  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.
#-------------------------------------------------------------------------------

use strict;

my $Version=4.8;
my $InstallArch='/usr/lib/polymake';

sub usage {
  print STDERR <<'.';
usage: polymake-config --help | --version | [--debug | --sanitize] --OPTION

Print bits of polymake configuration useful to compose Makefiles
for programs linked with its callable library.

OPTION may be one of:
  --cc          print the name of C++ compiler and linker
  --cflags      print the C++ compiler flags without header paths
  --includes    print the C++ compiler flags for header paths
  --ldflags     print the linker flags
  --libs        print the libraries to link with
.
  exit(0);
}

@ARGV || usage;

my $root='/usr/share/polymake';
do "$root/support/install_utils.pl";
die $@ if $@;
my %ConfigFlags=load_config_file("$InstallArch/config.ninja", $root);

if ($ConfigFlags{LDcallableFLAGS} eq "none") {
   die <<'.';
polymake has been built without callable library,
probably because of missing shared library libperl.
.
}

my $tmpdir;
foreach ($ENV{TMPDIR}, "/tmp", "/var/tmp", ".", $ENV{HOME}) {
   if (defined($_) && -d $_ && -w _ && -x _) {
      $tmpdir=$_; last;
   }
}
defined($tmpdir) or die <<'.';
Can't find any writable directory for temporary files;
Please set enviroment variable TMPDIR to an appropriate location.
.
my $tmpfile="$tmpdir/polymake-config-$$";
my ($mode, $mode_asked);

while (defined ($_=shift)) {
   if ($_ eq "--debug") {
      if (defined $mode_asked) {
         usage;
      } else {
         $mode="Debug";
      }

   } elsif ($_ eq "--sanitize") {
      if (defined $mode_asked) {
         usage;
      } else {
         $mode="San";
      }

   } elsif ($_ eq "--version") {
      print $Version, "\n";

   } elsif ($_ eq "--cc") {
      print $ConfigFlags{CXX}, "\n";

   } elsif ($_ eq "--cflags") {
      my ($major, $minor)=split /\./, $Version;
      my $version_for_c=sprintf("%d%02d", $major, $minor);
      $_="-DPOLYMAKE_VERSION=$version_for_c $ConfigFlags{CsharedFLAGS} $ConfigFlags{CXXFLAGS}";
      if ($^O eq "darwin") {
         s/\$\{ARCHFLAGS\}/$ConfigFlags{ARCHFLAGS}/;
      }

      # include paths are reported separately
      s/-I\S+//g;
      # do not impose the strict warning policy on foreign software
      s/-W(?:all|error)(?:\s|$)//g;
      # strip spaces
      s/^\s+//; s/\s+$//; s/\s{2,}/ /g;

      $mode_asked=1;
      if ($mode eq "Debug") {
         print "$_ $ConfigFlags{CXXDEBUG} -DPOLYMAKE_DEBUG=1\n";
      } elsif ($mode eq "San") {
         print "$_ $ConfigFlags{CXXSANITIZE} -DPOLYMAKE_DEBUG=0 $ConfigFlags{PERLSANITIZE}\n";
      } else {
         print "$_ $ConfigFlags{CXXOPT} -DPOLYMAKE_DEBUG=0\n";
      }

   } elsif ($_ eq "--includes") {
      my $inc=join(" ", grep { /^-I/ } split /\s+/, $ConfigFlags{CXXFLAGS});
      if (glob "$ConfigFlags{InstallInc}/polymake/external/*") {
         $inc="-I$ConfigFlags{InstallInc}/polymake/external $inc";
      }
      if ($inc !~ /(?:^|\s)-I$ConfigFlags{InstallInc}(?:\s|$)/) {
         $inc="-I$ConfigFlags{InstallInc} $inc";
      }

      # collect standard include paths of the C++ compiler and exclude them from the result
      open CF, ">$tmpfile.cc" or die "can't create temporary file $tmpfile.cc: $!\n";
      print CF "int main() { return 0; }\n";
      close CF;
      open CC, "$ConfigFlags{CXX} -o $tmpfile.bin -v $tmpfile.cc 2>&1 |" or die "can't run C++ compiler $ConfigFlags{CXX}: $!\n";
      while (<CC>) {
         last if (/^\#include.*starts here/i);
      }
      while (<CC>) {
         last if /end of search list/i;
         if (! /^\#/ && /(\S+)/) {
            my $dir=$1;
            $inc =~ s/(^|\s)-I$dir(\s\$)/$1$2/;
         }
      }
      close CC;
      $inc=~s/^\s+//; $inc=~s/\s+$//; $inc=~s/\s{2,}/ /g;
      print $inc, "\n";

   } elsif ($_ eq "--ldflags") {
      my $ldflags=$ConfigFlags{LDFLAGS};
      if ($ldflags !~ /(?:^|\s)-L$ConfigFlags{InstallLib}(?:\s|$)/) {
         $ldflags="-L$ConfigFlags{InstallLib} $ldflags";
      }
      my $add_rpath=1;

      # collect standard library paths of the C++ compiler and exclude them from the result
      open CF, ">$tmpfile.cc" or die "can't create temporary file $tmpfile.cc: $!\n";
      print CF "int main() { return 0; }\n";
      close CF;
      open CC, "$ConfigFlags{CXX} -o $tmpfile.bin -v $tmpfile.cc 2>&1 |" or die "can't run C++ compiler $ConfigFlags{CXX}: $!\n";
      while (<CC>) {
         if (/^LIBRARY_PATH=/i) {
            foreach my $dir (split /:/, $') {
               $ldflags =~ s/(^|\s)-L$dir(\s\$)/$1$2/;
               $add_rpath &&= $dir ne $ConfigFlags{InstallLib};
            }
            last;
         }
      }
      close CC;
      if ($^O eq "darwin") {
         $ldflags = "$ConfigFlags{ARCHFLAGS} $ldflags -flat_namespace";
      } else {
         $ldflags .= " -Wl,-E";
         if ($add_rpath) {
            $ldflags .= " -Wl,-rpath,$ConfigFlags{InstallLib}";
         }
      }
      $ldflags =~ s/^\s+//; $ldflags =~ s/\s+$//; $ldflags =~ s/\s{2,}/ /g;

      $mode_asked = 1;
      if ($mode eq "Debug") {
         print "$ldflags $ConfigFlags{CXXDEBUG}\n";
      } elsif ($mode eq "San") {
         print "$ldflags $ConfigFlags{CXXSANITIZE} $ConfigFlags{PERLSANITIZE}\n";
      } else {
         print $ldflags, "\n";
      }

   } elsif ($_ eq "--libs") {
      print "-lpolymake -lpolymake-apps $ConfigFlags{LIBS}\n";

   } else {
      usage;
   }
}

END {
   if (defined $tmpfile) {
      unlink $_ for glob "$tmpfile*";
   }
}

# Local Variables:
# mode: perl
# cperl-indent-level:3
# indent-tabs-mode:nil
# End:
