1#!/usr/local/bin/perl -w 2# $Id: Makefile.PL,v 1.476 2017/11/28 05:28:04 rmeden Exp $ 3 4use ExtUtils::MakeMaker; 5use Config; 6use File::Basename (); 7use File::Find; 8 9# Don't use ':config pass_through' because that requires Getopt::Long 10# 2.24 or later, and we don't have a clean way to require that. 11# 12use Getopt::Long; Getopt::Long::Configure('pass_through'); 13 14# Suppress 'isn't numeric' warnings from MakeMaker - see 15# <http://sourceforge.net/tracker/?func=detail&atid=424135&aid=870170&group_id=39046>. 16# 17$SIG{__WARN__} = sub { 18 for (my $msg = shift) { 19 $_ = "warning: something's wrong" if not defined; 20 warn $_ 21 unless /Argument .+ isn.t numeric in numeric lt .+MakeMaker.pm/; 22 } 23}; 24 25# ExtUtils::MakeMaker before 6.21 or so has a bug when PREFIX is not 26# given explicitly - 27# <http://article.gmane.org/gmane.comp.tv.xmltv.devel/3634>. 28# 29unless ($ExtUtils::MakeMaker::VERSION ge 6.21) { 30 if (not grep /^PREFIX=/, @ARGV) { 31 warn "You may want to explicitly give PREFIX to work around MakeMaker bugs.\n"; 32 } 33} 34 35use strict; 36 37sub test_module( $$ ); 38sub check_date_manip(); 39sub test_special( $$ ); 40sub targets( $ ); 41 42if ($] == 5.006) { 43 warn <<END 44Some installations of perl 5.6.0 are buggy and crash while running 45this script. If you get 'segmentation fault' below, please report it 46to the xmltv-users mailing list so we can try to work around the bug. 47At present the only known fix is to upgrade to a newer perl version 48such as 5.6.1 or 5.8.3. 49END 50; 51} 52 53# A couple of undocumented options to help with building the Windows 54# distribution even on hosts that don't have all the necessary 55# modules. By default, we only warn if dependencies are missing. 56# If --strict-deps is passed in, then the whole process fails. 57# 58my $opt_strictdeps = 0; 59my $opt_yes = 0; 60my $opt_default = 0; 61my $opt_components; 62my $opt_exclude; 63GetOptions('strict-deps' => \$opt_strictdeps, # be strict about dependencies 64 yes => \$opt_yes, # answer yes to all questions 65 default => \$opt_default, # answer default to all questions 66 'components=s' => \$opt_components, 67 'exclude=s' => \$opt_exclude, 68 ); 69 70our $VERSION; 71$VERSION = '0.5.70'; 72 73# Fragment of Makefile text to give the directory where files should 74# be installed. The extra '.' in the middle of the path is to avoid 75# beginning with '//', which means a network share on Cygwin. 76# 77my $location = '$(DESTDIR)/./$(PREFIX)'; 78 79our %extra_constants; 80%extra_constants 81 = (INST_PLAINDOC => 'blib/doc', 82 INSTALLPLAINDOC => "$location/share/doc/xmltv-$::VERSION", 83 INST_SHARE => 'blib/share', 84 INSTALLSHARE => "$location/share/xmltv", 85 86 # Manual page constants, shouldn't really be needed, but work 87 # around bugs and make sure this stuff is the same across 88 # MakeMaker versions. 89 INSTALLMAN1DIR => "$location/man/man1", 90 INSTALLMAN3DIR => "$location/man/man3", 91 MAN3EXT => '3', 92 93 # Directory to install into when making Windows binary dist. 94 WINDOWS_DIST => "xmltv-$VERSION-win32", 95 VERSION => "$VERSION", 96 ); 97 98# The following lists of dependencies and files to be installed may 99# get modified later depending on what the user chooses. 100# 101 102# Documentation files to be installed. This is a global variable 103# because it is accessed by some code we add to MakeMaker. 104# 105our @docs; 106@docs = qw(doc/COPYING doc/QuickStart doc/README.win32 README); 107 108# Executables to be installed. 109my @exes 110 = qw(filter/tv_augment_tz 111 filter/tv_extractinfo_en 112 filter/tv_extractinfo_ar 113 filter/tv_grep 114 filter/tv_sort 115 filter/tv_to_latex 116 filter/tv_to_text 117 filter/tv_to_potatoe 118 filter/tv_cat 119 filter/tv_split 120 filter/tv_imdb 121 filter/tv_remove_some_overlapping 122 filter/tv_count 123 filter/tv_merge 124 filter/tv_augment 125 tools/tv_validate_grabber 126 tools/tv_validate_file 127 tools/tv_find_grabbers 128 ); 129 130# Libraries to be installed. 131my %pm 132 = ('lib/XMLTV.pm' => '$(INST_LIBDIR)/XMLTV.pm', 133 'lib/TZ.pm' => '$(INST_LIBDIR)/XMLTV/TZ.pm', 134 'lib/Clumps.pm' => '$(INST_LIBDIR)/XMLTV/Clumps.pm', 135 'lib/Usage.pm' => '$(INST_LIBDIR)/XMLTV/Usage.pm', 136 'lib/Date.pm' => '$(INST_LIBDIR)/XMLTV/Date.pm', 137 'lib/Version.pm' => '$(INST_LIBDIR)/XMLTV/Version.pm', 138 'lib/Ask.pm' => '$(INST_LIBDIR)/XMLTV/Ask.pm', 139 'lib/Ask/Tk.pm' => '$(INST_LIBDIR)/XMLTV/Ask/Tk.pm', 140 'lib/Ask/Term.pm' => '$(INST_LIBDIR)/XMLTV/Ask/Term.pm', 141 'lib/GUI.pm' => '$(INST_LIBDIR)/XMLTV/GUI.pm', 142 'lib/ProgressBar.pm' => '$(INST_LIBDIR)/XMLTV/ProgressBar.pm', 143 'lib/ProgressBar/None.pm' => '$(INST_LIBDIR)/XMLTV/ProgressBar/None.pm', 144 'lib/ProgressBar/Term.pm' => '$(INST_LIBDIR)/XMLTV/ProgressBar/Term.pm', 145 'lib/ProgressBar/Tk.pm' => '$(INST_LIBDIR)/XMLTV/ProgressBar/Tk.pm', 146 'lib/Summarize.pm' => '$(INST_LIBDIR)/XMLTV/Summarize.pm', 147 'lib/Supplement.pm' => '$(INST_LIBDIR)/XMLTV/Supplement.pm', 148 'lib/IMDB.pm' => '$(INST_LIBDIR)/XMLTV/IMDB.pm', 149 'lib/Gunzip.pm' => '$(INST_LIBDIR)/XMLTV/Gunzip.pm', 150 'lib/Capabilities.pm' => '$(INST_LIBDIR)/XMLTV/Capabilities.pm', 151 'lib/Description.pm' => '$(INST_LIBDIR)/XMLTV/Description.pm', 152 'lib/Configure.pm' => '$(INST_LIBDIR)/XMLTV/Configure.pm', 153 'lib/Configure/Writer.pm' => '$(INST_LIBDIR)/XMLTV/Configure/Writer.pm', 154 'lib/Options.pm' => '$(INST_LIBDIR)/XMLTV/Options.pm', 155 'lib/ValidateFile.pm' => '$(INST_LIBDIR)/XMLTV/ValidateFile.pm', 156 'lib/ValidateGrabber.pm' => '$(INST_LIBDIR)/XMLTV/ValidateGrabber.pm', 157 'lib/PreferredMethod.pm' => '$(INST_LIBDIR)/XMLTV/PreferredMethod.pm', 158 'lib/Data/Recursive/Encode.pm' => '$(INST_LIBDIR)/XMLTV/Data/Recursive/Encode.pm', 159 'lib/Augment.pm' => '$(INST_LIBDIR)/XMLTV/Augment.pm', 160 'filter/Grep.pm' => '$(INST_LIBDIR)/XMLTV/Grep.pm', 161 'grab/Memoize.pm' => '$(INST_LIBDIR)/XMLTV/Memoize.pm', 162 'grab/Grab_XML.pm' => '$(INST_LIBDIR)/XMLTV/Grab_XML.pm', 163 'grab/DST.pm' => '$(INST_LIBDIR)/XMLTV/DST.pm', 164 'grab/Config_file.pm' => '$(INST_LIBDIR)/XMLTV/Config_file.pm', 165 'grab/Get_nice.pm' => '$(INST_LIBDIR)/XMLTV/Get_nice.pm', 166 'grab/Mode.pm' => '$(INST_LIBDIR)/XMLTV/Mode.pm', 167 ); 168 169# Modules required to install. 170my %prereqs 171 = ( 172 'LWP' => 5.65, 173 # XML::Parser is required by XML::Twig, but older versions have a 174 # bug when $SIG{__DIE__} is set (well, could be a perl bug, but 175 # anyway it doesn't appear with 2.34). 176 # 177 'XML::Parser' => 2.34, 178 'XML::Twig' => 3.10, 179 'Date::Manip' => 5.42, 180 'XML::Writer' => 0.600, 181 'Memoize' => 0, 182 'Storable' => 2.04, 183 'File::Slurp' => 0, 184 'XML::TreePP' => 0, 185 ); 186 187# Files which are run to generate source code. 188my %pl_files = ('filter/tv_grep.PL' => 'filter/tv_grep', 189 'tools/tv_validate_file.PL' => 'tools/tv_validate_file', 190 'tools/tv_validate_grabber.PL' => 'tools/tv_validate_grabber', 191 'lib/XMLTV.pm.PL' => 'lib/XMLTV.pm', 192 'lib/Supplement.pm.PL' => 'lib/Supplement.pm', 193 ); 194 195# Some tools which are generated from .PL files need the share/ 196# directory passed as an extra argument. 197# 198my @need_share = ('tools/tv_validate_file', 199 'tools/tv_validate_grabber', 200 'lib/Supplement.pm', 201 ); 202 203# Files to be installed in the system-wide share/ directory. 204my %share_files = ('xmltv.dtd' => 'xmltv.dtd', 205 'xmltv-lineups.xsd' => 'xmltv-lineups.xsd', 206 'filter/augment/augment.conf' => 'tv_augment/augment.conf', 207 'filter/augment/augment.rules' => 'tv_augment/augment.rules', 208 ); 209 210# Files which 'make clean' should remove, but doesn't by default, so 211# we have to patch it. 212# 213my @to_clean = ('filter/tv_grep', 214 'tools/tv_validate_file', 215 'tools/tv_validate_grabber', 216 'lib/XMLTV.pm', 217 'lib/Supplement.pm', 218 ); 219 220# Extra dependencies to add to the Makefile. 221my @deps = ('filter/tv_grep' => [ qw(filter/tv_grep.in pm_to_blib) ], 222 'tools/tv_validate_file' => [ qw(tools/tv_validate_file.in) ], 223 'tools/tv_validate_grabber' => [ qw(tools/tv_validate_grabber.in) ], 224 'lib/XMLTV.pm' => [ 'lib/XMLTV.pm.in' ], 225 'lib/Supplement.pm' => [ 'lib/Supplement.pm.in' ], 226 ); 227 228# Some grabbers which are generated from .PL files need the share/ 229# directory passed as an extra argument. 230# 231my @grab_need_share; 232 233# 'Recommended but not required'. It isn't currently handled to have 234# the same module in both sets. 235# 236my %recommended 237 = ( 238 'Lingua::EN::Numbers::Ordinate' => 0, 239 'Lingua::Preferred' => '0.2.4', 240 'Term::ProgressBar' => 2.03, 241 'Compress::Zlib' => 0, 242 'Unicode::String' => 0, 243 ); 244 245# And Log::TraceMessages is 'suggested' but we don't warn about that. 246 247if ($opt_yes) { 248 *ask = sub { print "$_[0] yes\n"; 1 }; 249} 250elsif ($opt_default) { 251 *ask = sub { print "$_[0] $_[2]\n"; $_[2] }; 252} 253else { 254 require './lib/Ask/Term.pm'; 255 *ask = \&XMLTV::Ask::Term::ask_boolean; 256} 257 258# Weird shit happens when you change things like PREFIX without 259# rebuilding everything explicitly. 260# 261if (-e 'Makefile') { 262 warn <<END 263There is already a Makefile. To avoid weird problems it is 264recommended you run 'make distclean' to clear out old built files 265before generating a new Makefile. 266 267END 268; 269 if (! ask(0, "Do you wish to continue anyway?", 0)) { 270 exit(1); 271 } 272} 273 274# Now prompt about how much to install. This is really only to 275# reduce dependencies. In the long run things like tv_check can be 276# spun off into separate projects. 277# 278my @opt_components 279 = ( 280 281 { name => 'tv_grab_ar', 282 blurb => 'Grabber for Argentina', 283 exes => [ 'grab/ar/tv_grab_ar' ], 284 prereqs => { 'HTML::TreeBuilder' => 0, 285 'HTML::Entities' => 0, 286 'HTTP::Cookies' => 0, 287 'LWP::UserAgent' => 0, 288 'JSON::PP' => 0, 289 'Date::Language' => 0, }, 290 }, 291 292# Disabled 2006-04-12 since it doesn't provide data anymore. 293# { name => 'tv_grab_au', 294# blurb => 'Grabber for Australia', 295# exes => [ 'grab/au/tv_grab_au' ], 296# deps => [ 'grab/au/tv_grab_au' => [ 'grab/au/tv_grab_au.in' ] ], 297# pl_files => { 'grab/au/tv_grab_au.PL' => 'grab/au/tv_grab_au' }, 298# to_clean => [ 'grab/au/tv_grab_au' ], 299# share_files => { 'grab/au/channel_ids' => 'tv_grab_au/channel_ids' }, 300# grab_need_share => [ 'au' ], 301# }, 302 303# 2008-11-09 disabled after ident string was blocked 304# { name => 'tv_grab_be', 305# blurb => 'Grabber for Belgium and Luxemburg', 306# exes => [ 'grab/be/tv_grab_be' ], 307# pl_files => { 'grab/be/tv_grab_be.PL' => 'grab/be/tv_grab_be' }, 308# share_files => { 'grab/be/channel_ids_fr' => 'tv_grab_be/channel_ids_fr', 309# 'grab/be/channel_ids_nl' => 'tv_grab_be/channel_ids_nl' }, 310# to_clean => [ 'grab/be/tv_grab_be' ], 311# deps => [ 'grab/be/tv_grab_be' => [ 'grab/be/tv_grab_be.in' ] ], 312# grab_need_share => [ 'be' ], 313# prereqs => { 'HTML::Entities' => 1.27 } , 314# }, 315 316# { name => 'tv_grab_br', 317# blurb => 'Grabber for Brazil', 318# exes => [ 'grab/br/tv_grab_br' ], 319# prereqs => { 'HTML::TreeBuilder' => 0 , 320# 'HTML::Entities' => 1.27 , } 321# }, 322 323# disabled because it broke due to site changes 2009-03-08 324# { name => 'tv_grab_br_net', 325# blurb => 'Grabber for Brazil NET Cable', 326# exes => [ 'grab/br_net/tv_grab_br_net' ], 327# prereqs => { 'WWW::Mechanize' => 1.16 , 328# 'HTTP::Cookies' => 1.39 , } 329# }, 330 331# disabled since blocked by www.fernsehen.ch guys 332# { name => 'tv_grab_ch', 333# blurb => 'Grabber for Switzerland', 334# exes => [ 'grab/ch/tv_grab_ch' ], 335# deps => [ 'grab/ch/tv_grab_ch' => [ 'grab/ch/tv_grab_ch.in' ] ], 336# pl_files => { 'grab/ch/tv_grab_ch.PL' => 'grab/ch/tv_grab_ch' }, 337# to_clean => [ 'grab/ch/tv_grab_ch' ], 338# share_files => { 'grab/ch/channel_ids' => 'tv_grab_ch/channel_ids' }, 339# grab_need_share => [ 'ch' ], 340# }, 341 342# disabled after ident string was blocked 343# { name => 'tv_grab_ch_bluewin', 344# blurb => 'Grabber for Switzerland', 345# exes => [ 'grab/ch_bluewin/tv_grab_ch_bluewin' ], 346# deps => [ 'grab/ch_bluewin/tv_grab_ch_bluewin' 347# => [ 'grab/ch_bluewin/tv_grab_ch_bluewin.in' ] ], 348# pl_files => { 'grab/ch_bluewin/tv_grab_ch_bluewin.PL' 349# => 'grab/ch_bluewin/tv_grab_ch_bluewin' }, 350# to_clean => [ 'grab/ch_bluewin/tv_grab_ch_bluewin' ], 351# share_files => { 'grab/ch_bluewin/channel_ids' 352# => 'tv_grab_ch_bluewin/channel_ids' }, 353# grab_need_share => [ 'ch_bluewin' ], 354# prereqs => { 'HTML::Entities' => 1.27, 355# 'HTML::TreeBuilder' => 0 }, 356# }, 357 358 { name => 'tv_grab_ch_search', 359 blurb => 'Grabber for Switzerland', 360 exes => [ 'grab/ch_search/tv_grab_ch_search' ], 361 deps => [ 'grab/ch_search/tv_grab_ch_search' 362 => [ 'grab/ch_search/tv_grab_ch_search.in' ] ], 363 pl_files => { 'grab/ch_search/tv_grab_ch_search.PL' 364 => 'grab/ch_search/tv_grab_ch_search' }, 365 to_clean => [ 'grab/ch_search/tv_grab_ch_search' ], 366# share_files => { 'grab/ch_search/channel_ids' 367# => 'tv_grab_ch_search/channel_ids' }, 368 grab_need_share => [ 'ch_search' ], 369 prereqs => { 'HTML::Entities' => 1.27, 370 'HTML::TreeBuilder' => 0, }, 371 }, 372 373# 2008-07-22 - removed by rmeden, website changes, won't be fixed 374# { name => 'tv_grab_dk', 375# blurb => 'Grabber for Denmark', 376# exes => [ 'grab/dk/tv_grab_dk' ], 377# prereqs => { 'HTML::TreeBuilder' => 0 } }, 378 379 { name => 'tv_grab_dk_dr', 380 blurb => 'Grabber for Denmark (dr.dk)', 381 exes => [ 'grab/dk_dr/tv_grab_dk_dr' ], 382 prereqs => { 'Data::Dumper' => 0, 383 'LWP::UserAgent' => 0, 384 'IO::Scalar' => 0, 385 'DateTime' => 0, 386 'JSON' => 0, }, 387 }, 388 389 { name => 'tv_grab_dtv_la', 390 blurb => 'Grabber for Latin America & Caribbean', 391 exes => [ 'grab/dtv_la/tv_grab_dtv_la' ], 392 prereqs => { 'LWP::UserAgent' => 0, 393 'HTTP::Cookies' => 0, 394 'HTML::TreeBuilder' => 0, 395 'JSON::PP' => 0, 396 'Date::Manip' => 0, 397 'Date::Parse' => 0, 398 'Date::Language' => 0, }, 399 }, 400 401# rmeden 2012-06-11 broken since 2011-11-25 402# { name => 'tv_grab_ee', 403# blurb => 'Grabber for Estonia', 404# exes => [ 'grab/ee/tv_grab_ee' ], 405# prereqs => { 'LWP::Simple' => 0 } }, 406 407# 2009-03-08 removed due to breakage after source site changes 408# { name => 'tv_grab_es', 409# blurb => 'Grabber for Spain - Analogic Terrestrial/Cable', 410# exes => [ 'grab/es/tv_grab_es' ], 411# prereqs => { 'HTML::TreeBuilder' => 0 } }, 412 413# tv_grab_es_digital no longer functioning due to site changes 414# { name => 'tv_grab_es_digital', 415# blurb => 'Grabber for Spain - Digital Satellite (D+)', 416# exes => [ 'grab/es_digital/tv_grab_es_digital' ], 417# prereqs => { 'HTML::TreeBuilder' => 0 } }, 418 419 { name => 'tv_grab_es_laguiatv', 420 blurb => 'Alternative grabber for Spain', 421 exes => [ 'grab/es_laguiatv/tv_grab_es_laguiatv' ], 422 prereqs => { 'HTML::TreeBuilder' => 0, }, 423 }, 424 425# rmeden 2012-06-11 broken since 2012-03-29 426# { name => 'tv_grab_es_miguiatv', 427# blurb => 'Alternative grabber for Spain using miguiatv.com', 428# exes => [ 'grab/es_miguiatv/tv_grab_es_miguiatv' ], 429# prereqs => { 'HTML::TreeBuilder' => 0 } },# 430 431 { name => 'tv_grab_eu_dotmedia', 432 blurb => 'Grabber for Europe (xmltv.se / dotmedia)', 433 exes => [ 'grab/eu_dotmedia/tv_grab_eu_dotmedia' ], 434 prereqs => { 'XML::LibXML' => 0, 435 'Compress::Zlib' => 0, 436 'IO::Stringy' => 0, 437 'HTTP::Cache::Transparent' => 0, }, 438 }, 439 440 # knowledgejunkie 2017-09-30 disbled as no longer providing data 441 # { name => 'tv_grab_eu_egon', 442 # blurb => 'Grabber for german speaking area (Egon zappt)', 443 # exes => [ 'grab/eu_egon/tv_grab_eu_egon' ], 444 # pl_files => { 'grab/eu_egon/tv_grab_eu_egon.PL' 445 # => 'grab/eu_egon/tv_grab_eu_egon' }, 446 # to_clean => [ 'grab/eu_egon/tv_grab_eu_egon' ], 447 # deps => [ 'grab/eu_egon/tv_grab_eu_egon' 448 # => [ 'grab/se_swedb/tv_grab_se_swedb.in' ] ], 449 # prereqs => { 'XML::LibXML' => 0, 450 # 'Compress::Zlib' => 0, 451 # 'IO::Stringy' => 0, 452 # 'HTTP::Cache::Transparent' => 0, }, 453 # }, 454 455 { name => 'tv_grab_eu_epgdata', 456 blurb => '$$ Grabber for some European countries (epgdata.com)', 457 exes => [ 'grab/eu_epgdata/tv_grab_eu_epgdata' ], 458 share_files => { 'grab/eu_epgdata/channel_ids' => 'tv_grab_eu_epgdata/channel_ids' }, 459 prereqs => { 'XML::Twig' => 0, 460 'Archive::Zip' => 0, 461 'HTML::Entities' => 0, 462 'LWP::Simple' => 0, 463 'File::Temp' => 0, 464 'DateTime::Format::Strptime' => 0, }, 465 }, 466 467 { name => 'tv_grab_fi', 468 blurb => 'Grabber for Finland', 469 exes => [ 'grab/fi/tv_grab_fi' ], 470 deps => [ 471 'grab/fi/tv_grab_fi' => [ 472 'grab/fi/tv_grab_fi.pl', 473 'grab/fi/fi/common.pm', 474 'grab/fi/fi/day.pm', 475 'grab/fi/fi/programme.pm', 476 'grab/fi/fi/programmeStartOnly.pm', 477 'grab/fi/fi/source/foxtv.pm', 478 'grab/fi/fi/source/iltapulu.pm', 479 'grab/fi/fi/source/telkku.pm', 480 'grab/fi/fi/source/yle.pm', 481 ], 482 ], 483 pl_files => { 'grab/fi/merge.PL' => 'grab/fi/tv_grab_fi' }, 484 to_clean => [ 'grab/fi/tv_grab_fi' ], 485 prereqs => { 'Encode' => 0, 486 'HTML::TreeBuilder' => 0, 487 'JSON' => 0, 488 'LWP::Protocol::https' => 0, 489 'Time::Local' => 0, }, 490 }, 491 492 { name => 'tv_grab_fi_sv', 493 blurb => 'Grabber for Finland (Swedish)', 494 exes => [ 'grab/fi_sv/tv_grab_fi_sv' ], 495 prereqs => { 'DateTime' => 0, 496 'IO::Scalar' => 0, 497 'HTML::TreeBuilder' => 0, }, 498 }, 499 500 { name => 'tv_grab_fr', 501 blurb => 'Grabber for France', 502 exes => [ 'grab/fr/tv_grab_fr' ], 503 prereqs => { 'DateTime' => 0, 504 'DateTime::Duration' => 0, 505 'DateTime::TimeZone' => 0, 506 'HTML::Entities' => 1.27, 507 'HTML::TreeBuilder' => 0, }, 508 }, 509 510 { name => 'tv_grab_fr_kazer', 511 blurb => 'Grabber for France (Kazer)', 512 exes => [ 'grab/fr_kazer/tv_grab_fr_kazer' ], 513 prereqs => { 'IO::Uncompress::Unzip' => 0, }, 514 }, 515 516# 517# 2017-01-22 - source site (www.gonix.net/ gone. 518# 519# { name => 'tv_grab_hr', 520# blurb => 'Grabber for Croatia', 521# exes => [ 'grab/hr/tv_grab_hr' ], 522# pl_files => { 'grab/hr/tv_grab_hr.PL' 523# => 'grab/hr/tv_grab_hr' }, 524# to_clean => [ 'grab/hr/tv_grab_hr' ], 525# deps => [ 'grab/hr/tv_grab_hr' 526# => [ 'grab/se_swedb/tv_grab_se_swedb.in' ] ], 527# prereqs => { 'XML::LibXML' => 0, 528# 'Compress::Zlib' => 0, 529# 'IO::Stringy' => 0, 530# 'HTTP::Cache::Transparent' => 0, }, 531# }, 532 533 { name => 'tv_grab_huro', 534 blurb => 'Grabber for Slovakia (Hungary, Romania broken)', 535 exes => [ 'grab/huro/tv_grab_huro' ], 536 pl_files => { 'grab/huro/tv_grab_huro.PL' 537 => 'grab/huro/tv_grab_huro' }, 538 share_files => { 'grab/huro/jobmap' => 'tv_grab_huro/jobmap', 539 'grab/huro/catmap.hu' => 'tv_grab_huro/catmap.hu', 540 'grab/huro/catmap.ro' => 'tv_grab_huro/catmap.ro', 541 'grab/huro/catmap.sk' => 'tv_grab_huro/catmap.sk', 542 'grab/huro/catmap.cz' => 'tv_grab_huro/catmap.cz', 543 }, 544 to_clean => [ 'grab/huro/tv_grab_huro' ], 545 deps => [ 'grab/huro/tv_grab_huro' 546 => [ 'grab/huro/tv_grab_huro.in' ] ], 547 grab_need_share => [ 'huro' ], 548 prereqs => { 'HTML::TreeBuilder' => 0, 549 'JSON' => 0, }, 550 }, 551 552 { name => 'tv_grab_il', 553 blurb => 'Grabber for Israel', 554 exes => [ 'grab/il/tv_grab_il' ], 555 }, 556 557# 2013-05-13 xmltv feed disabled by What's On due to TOS violations. It may come back 558# { name => 'tv_grab_in', 559# blurb => 'Grabber for India (zipazap.com)', 560# exes => [ 'grab/in/tv_grab_in' ], 561# prereqs => { 'XML::LibXML' => 0, 562# 'IO::Scalar' => 0, 563# }, 564# }, 565 566 { name => 'tv_grab_is', 567 blurb => 'Grabber for Iceland', 568 exes => [ 'grab/is/tv_grab_is' ], 569 share_files => { 'grab/is/category_map' => 'tv_grab_is/category_map' }, 570 prereqs => { 'XML::LibXSLT' => 0, 571 'XML::DOM' => 0, }, 572 }, 573 574 { name => 'tv_grab_it', 575 blurb => 'Grabber for Italy', 576 exes => [ 'grab/it/tv_grab_it' ], 577 pl_files => { 'grab/it/tv_grab_it.PL' => 'grab/it/tv_grab_it' }, 578 share_files => { 'grab/it/channel_ids' => 'tv_grab_it/channel_ids' }, 579 to_clean => [ 'grab/it/tv_grab_it', 'grab/it/tv_grab_it.in2' ], 580 deps => [ 'grab/it/tv_grab_it' => [ 'grab/it/tv_grab_it.in' ] ], 581 grab_need_share => [ 'it' ], 582 }, 583 584 { name => 'tv_grab_it_dvb', 585 blurb => 'Grabber for Italy from DVB-S stream', 586 exes => [ 'grab/it_dvb/tv_grab_it_dvb' ], 587 pl_files => { 'grab/it_dvb/tv_grab_it_dvb.PL' => 'grab/it_dvb/tv_grab_it_dvb' }, 588 share_files => { 'grab/it_dvb/channel_ids' => 'tv_grab_it_dvb/channel_ids', 589 'grab/it_dvb/sky_it.dict' => 'tv_grab_it_dvb/sky_it.dict', 590 'grab/it_dvb/sky_it.themes' => 'tv_grab_it_dvb/sky_it.themes', 591 }, 592 to_clean => [ 'grab/it_dvb/tv_grab_it_dvb' ], 593 deps => [ 'grab/it_dvb/tv_grab_it_dvb' => [ 'grab/it_dvb/tv_grab_it_dvb.in' ] ], 594 grab_need_share => [ 'it_dvb' ], 595 prereqs => { 'Data::Dump' => 0, 596 'IO::Select' => 0, 597 'Linux::DVB' => 0, 598 'Time::HiRes' => 0, } , 599 }, 600 601# 2009-03-05 rmeden - source site seems to be blocking our agent string 602# { name => 'tv_grab_jp', 603# blurb => 'Grabber for Japan', 604# exes => [ 'grab/jp/tv_grab_jp' ], 605# prereqs => { 'HTML::TreeBuilder' => 0, 606# 'Text::Kakasi' => 0 }, 607# }, 608 609 { name => 'tv_grab_na_dd', 610 blurb => '$$ Grabber for North America-schedulesdirect.org', 611 exes => [ 'grab/na_dd/tv_grab_na_dd' ], 612 pl_files => { 'grab/na_dd/tv_grab_na_dd.PL' => 'grab/na_dd/tv_grab_na_dd' }, 613 deps => [ 'grab/na_dd/tv_grab_na_dd' => [ 'grab/na_dd/tv_grab_na_dd.in' ] ], 614 to_clean => [ 'grab/na_dd/tv_grab_na_dd' ], 615 prereqs => { 'SOAP::Lite' => 0.67, 616 'Term::ReadKey' => 0, 617 'XML::Twig' => 3.28, }, 618 grab_need_share => [ 'na_dd' ], 619 }, 620 621 { name => 'tv_grab_na_dtv', 622 blurb => 'Grabber for North America (DirecTV)', 623 exes => [ 'grab/na_dtv/tv_grab_na_dtv' ], 624 prereqs => { 625 'DateTime' => 0, 626 'HTTP::Cookies' => 0, 627 'LWP::UserAgent' => 0, 628 'JSON::PP' => 0, 629 'HTML::TokeParser' => 0, }, 630 }, 631 632# 2013-02-02 disabled after site changes broke grabber (no <IMG> tags!) 633# { name => 'tv_grab_na_icons', 634# blurb => 'Grabber for North American Channel Icons', 635# exes => [ 'grab/na_icons/tv_grab_na_icons' ], 636# deps => [ 'grab/na_icons/tv_grab_na_icons' => [ 'grab/na_icons/tv_grab_na_icons.in' ] ], 637# pl_files => { 'grab/na_icons/tv_grab_na_icons.PL' => 'grab/na_icons/tv_grab_na_icons' }, 638# to_clean => [ 'grab/na_icons/tv_grab_na_icons' ], 639# prereqs => { 'HTML::TreeBuilder' => 0, 640# 'XML::Twig' => 3.28, 641# 'WWW::Mechanize' => 1.02 }, 642# grab_need_share => [ 'na_icons' ], 643# }, 644 645 { name => 'tv_grab_na_tvmedia', 646 blurb => 'Grabber for North America (TVMedia)', 647 exes => [ 'grab/na_tvmedia/tv_grab_na_tvmedia' ], 648 prereqs => { 'XML::LibXML' => 0, 649 'LWP::Simple' => 0, }, 650 }, 651 652# rmeden 2008-02-13 disabled after site changes broke grabber 653# { name => 'tv_grab_nc', 654# blurb => 'Grabber for Nouvelle Caledonie Island (France)', 655# exes => [ 'grab/nc/tv_grab_nc' ], 656# prereqs => { 'HTML::TreeBuilder' => 0 , 657# 'HTML::Entities' => 0 } }, 658 659 { name => 'tv_grab_nl', 660 blurb => 'Grabber for the Netherlands', 661 exes => [ 'grab/nl/tv_grab_nl' ], 662 prereqs => { 'HTTP::Cache::Transparent' => 0, 663 'HTML::TreeBuilder' => 0, 664 'HTML::Entities' => 0, 665 'IO::File' => 0, 666 'Date::Parse' => 0, 667 'Date::Format' => 0, 668 'DateTime' => 0, 669 'Encode' => 0, 670 'JSON::PP' => 0, }, 671 }, 672 673# 2008-07-12 - removed by rmeden, not getting programs for a while. 674# { name => 'tv_grab_nl_wolf', 675# blurb => 'Alternative grabber for the Netherlands', 676# exes => [ 'grab/nl_wolf/tv_grab_nl_wolf' ], 677# prereqs => { 'HTML::TreeBuilder' => 0 } }, 678 679# depreciate tv_grab_no as it is no longer supported (per author, cwattengard@gmail.com) 680# has been replaced by tv_grab_no_gfeed 681# 682# { name => 'tv_grab_no', 683# blurb => 'Grabber for Norway', 684# exes => [ 'grab/no/tv_grab_no' ], 685# prereqs => { 'HTML::Entities' => 1.27 }, 686# }, 687 688# 2016-03-16 - disabled by knowledgejunkie, not well for many months 689# and data.epg.no server no longer online 690# { name => 'tv_grab_no_gfeed', 691# blurb => 'Grabber for Norway (gfeed.info)', 692# exes => [ 'grab/no_gfeed/tv_grab_no_gfeed' ], 693# pl_files => { 'grab/no_gfeed/tv_grab_no_gfeed.PL' 694# => 'grab/no_gfeed/tv_grab_no_gfeed' }, 695# to_clean => [ 'grab/no_gfeed/tv_grab_no_gfeed' ], 696# deps => [ 'grab/no_gfeed/tv_grab_no_gfeed' 697# => [ 'grab/se_swedb/tv_grab_se_swedb.in' ] ], 698# prereqs => { 'XML::LibXML' => 0, 699# 'Compress::Zlib' => 0, 700# 'IO::Stringy' => 0, 701# 'HTTP::Cache::Transparent' => 0, }, 702# }, 703 704# 705# 2017-01-22 Broken due to site changes 706# 707# { name => 'tv_grab_pt', 708# blurb => 'Grabber for Portugal', 709# exes => [ 'grab/pt/tv_grab_pt' ], 710# prereqs => { 'Getopt::Long' => 0, 711# 'HTML::TreeBuilder' => 0, 712# 'HTML::Entities' => 1.27, 713# 'HTTP::Cache::Transparent' => 0, 714# 'DateTime' => 0, 715# 'Encode' => 0, 716# 'JSON::PP' => 0, }, 717# }, 718 719 { name => 'tv_grab_pt_meo', 720 blurb => 'Grabber for Portugal (MEO)', 721 exes => [ 'grab/pt_meo/tv_grab_pt_meo' ], 722 prereqs => { 'DateTime' => 0, 723 'XML::LibXML' => 0, 724 'LWP' => 0, }, 725 }, 726 727# rmeden 2011-06-12 not working 728# { name => 'tv_grab_re', 729# blurb => 'Grabber for Reunion Island (France)', 730# exes => [ 'grab/re/tv_grab_re' ], 731# prereqs => { 'HTML::TreeBuilder' => 0 , 732# 'HTML::Entities' => 0 } }, 733 734 { name => 'tv_grab_se_swedb', 735 blurb => 'Grabber for Sweden', 736 exes => [ 'grab/se_swedb/tv_grab_se_swedb' ], 737 pl_files => { 'grab/se_swedb/tv_grab_se_swedb.PL' 738 => 'grab/se_swedb/tv_grab_se_swedb' }, 739 to_clean => [ 'grab/se_swedb/tv_grab_se_swedb' ], 740 deps => [ 'grab/se_swedb/tv_grab_se_swedb' 741 => [ 'grab/se_swedb/tv_grab_se_swedb.in' ] ], 742 prereqs => { 'XML::LibXML' => 0, 743 'Compress::Zlib' => 0, 744 'IO::Stringy' => 0, 745 'HTTP::Cache::Transparent' => 0, }, 746 }, 747 748 { name => 'tv_grab_se_tvzon', 749 blurb => 'Grabber for Sweden (tvzon.se)', 750 exes => [ 'grab/se_tvzon/tv_grab_se_tvzon' ], 751 pl_files => { 'grab/se_tvzon/tv_grab_se_tvzon.PL' 752 => 'grab/se_tvzon/tv_grab_se_tvzon' }, 753 to_clean => [ 'grab/se_tvzon/tv_grab_se_tvzon' ], 754 deps => [ 'grab/se_tvzon/tv_grab_se_tvzon' 755 => [ 'grab/se_swedb/tv_grab_se_swedb.in' ] ], 756 prereqs => { 'XML::LibXML' => 0, 757 'Compress::Zlib' => 0, 758 'IO::Stringy' => 0, 759 'HTTP::Cache::Transparent' => 0, }, 760 }, 761 762 { name => 'tv_grab_tr', 763 blurb => 'Grabber for Turkey (Digiturk)', 764 exes => [ 'grab/tr/tv_grab_tr' ], 765 prereqs => { 'HTTP::Cache::Transparent' => 1.0, 766 'LWP::UserAgent' => 0, 767 'HTTP::Cookies' => 0, 768 'DateTime' => 0, 769 'Date::Parse' => 0, 770 'Encode' => 0, 771 'URI::Escape' => 0, 772 'File::Path' => 0, }, 773 }, 774 775# 776# 2017-01-22 tv_grab_uk_atlas removed due to site rule changes 777# 778# { name => 'tv_grab_uk_atlas', 779# blurb => 'Fast grabber for UK and Ireland using Atlas database', 780# exes => [ 'grab/uk_atlas/tv_grab_uk_atlas' ], 781# share_files => { 782# 'grab/uk_atlas/tv_grab_uk_atlas.user.map.conf' 783# => 'tv_grab_uk_atlas/tv_grab_uk_atlas.user.map.conf', 784# 'grab/uk_atlas/tv_grab_uk_atlas.pa.genres.conf' 785# => 'tv_grab_uk_atlas/tv_grab_uk_atlas.pa.genres.conf', 786# 'grab/uk_atlas/tv_grab_uk_atlas.map.genres.conf' 787# => 'tv_grab_uk_atlas/tv_grab_uk_atlas.map.genres.conf', 788# 'grab/uk_atlas/tv_grab_uk_atlas.map.channels.conf' 789# => 'tv_grab_uk_atlas/tv_grab_uk_atlas.map.channels.conf', 790# 'grab/uk_atlas/cgi-bin/getatlas.pl' 791# => 'tv_grab_uk_atlas/cgi-bin/getatlas.pl', }, 792# prereqs => { 'HTTP::Cache::Transparent' => 1.0, 793# 'LWP::UserAgent' => 0, 794# 'HTTP::Cookies' => 0, 795# 'JSON::PP' => 0, 796# 'DateTime' => 0, 797# 'Date::Parse' => 0, 798# 'Encode' => 0, 799# 'URI::Escape' => 0, 800# 'File::Path' => 0, 801# 'Data::Dumper' => 0, 802# 'Pod::Usage' => 0, }, 803# }, 804 805 { name => 'tv_grab_uk_bleb', 806 blurb => 'Fast alternative grabber for the UK', 807 exes => [ 'grab/uk_bleb/tv_grab_uk_bleb' ], 808 pl_files => { 'grab/uk_bleb/tv_grab_uk_bleb.PL' => 'grab/uk_bleb/tv_grab_uk_bleb' }, 809 share_files => { 'grab/uk_bleb/icon_urls' => 'tv_grab_uk_bleb/icon_urls' }, 810 to_clean => [ 'grab/uk_bleb/tv_grab_uk_bleb' ], 811 deps => [ 'grab/uk_bleb/tv_grab_uk_bleb' => [ 'grab/uk_bleb/tv_grab_uk_bleb.in' ] ], 812 grab_need_share => [ 'uk_bleb' ], 813 prereqs => { 'IO::Stringy' => 0, 'Archive::Zip' => 0, }, 814 }, 815 816# [bilbo_uk] The Guardian have removed their online tv listings service @ 1/Oct/14 817# { name => 'tv_grab_uk_guardian', 818# blurb => 'Grabber for UK and Ireland using The Guardian website', 819# exes => [ 'grab/uk_guardian/tv_grab_uk_guardian' ], 820# share_files => { 821# 'grab/uk_guardian/tv_grab_uk_guardian.map.conf' 822# => 'tv_grab_uk_guardian/tv_grab_uk_guardian.map.conf', 823# }, 824# prereqs => { 'HTTP::Cache::Transparent' => 1.0, 825# 'DateTime' => 0, 826# 'File::Path' => 0, 827# 'Encode' => 0, }, 828# }, 829 830# knowledgejunkie 2016-06-17 data feed turned off after nearly 12 years 831# { name => 'tv_grab_uk_rt', 832# blurb => 'Grabber for UK and Ireland (Radio Times)', 833# exes => [ 'grab/uk_rt/tv_grab_uk_rt' ], 834# share_files => { 835# 'grab/uk_rt/channel_ids' 836# => 'tv_grab_uk_rt/channel_ids', 837# 'grab/uk_rt/prog_titles_to_process' 838# => 'tv_grab_uk_rt/prog_titles_to_process', 839# 'grab/uk_rt/regional_channels_by_postcode' 840# => 'tv_grab_uk_rt/regional_channels_by_postcode', 841# 'grab/uk_rt/channels_platforms' 842# => 'tv_grab_uk_rt/channels_platforms', 843# 'grab/uk_rt/utf8_fixups' 844# => 'tv_grab_uk_rt/utf8_fixups', 845# 'grab/uk_rt/channel_icons' 846# => 'tv_grab_uk_rt/channel_icons', 847# 848# 'grab/uk_rt/lineups/xmltv-lineups.xsl' 849# => 'tv_grab_uk_rt/lineups/xmltv-lineups.xsl', 850# 851# 'grab/uk_rt/lineups/lineups.xml' 852# => 'tv_grab_uk_rt/lineups/lineups.xml', 853# 854# 'grab/uk_rt/lineups/freesatfromsky.xml' 855# => 'tv_grab_uk_rt/lineups/freesatfromsky.xml', 856# 'grab/uk_rt/lineups/freesathd.xml' 857# => 'tv_grab_uk_rt/lineups/freesathd.xml', 858# 'grab/uk_rt/lineups/freesat.xml' 859# => 'tv_grab_uk_rt/lineups/freesat.xml', 860# 'grab/uk_rt/lineups/freeviewhd.xml' 861# => 'tv_grab_uk_rt/lineups/freeviewhd.xml', 862# 'grab/uk_rt/lineups/freeview.xml' 863# => 'tv_grab_uk_rt/lineups/freeview.xml', 864# 'grab/uk_rt/lineups/saorview.xml' 865# => 'tv_grab_uk_rt/lineups/saorview.xml', 866# 'grab/uk_rt/lineups/skyhd.xml' 867# => 'tv_grab_uk_rt/lineups/skyhd.xml', 868# 'grab/uk_rt/lineups/sky.xml' 869# => 'tv_grab_uk_rt/lineups/sky.xml', 870# 'grab/uk_rt/lineups/upcirelandhd.xml' 871# => 'tv_grab_uk_rt/lineups/upcirelandhd.xml', 872# 'grab/uk_rt/lineups/upcireland.xml' 873# => 'tv_grab_uk_rt/lineups/upcireland.xml', 874# 'grab/uk_rt/lineups/virginhd.xml' 875# => 'tv_grab_uk_rt/lineups/virginhd.xml', 876# 'grab/uk_rt/lineups/virgin.xml' 877# => 'tv_grab_uk_rt/lineups/virgin.xml', 878# 879# 'grab/uk_rt/lineups/freeview.map' 880# => 'tv_grab_uk_rt/lineups/freeview.map', 881# 'grab/uk_rt/lineups/freesat.map' 882# => 'tv_grab_uk_rt/lineups/freesat.map', 883# 'grab/uk_rt/lineups/saorview.map' 884# => 'tv_grab_uk_rt/lineups/saorview.map', }, 885# prereqs => { 'HTTP::Cache::Transparent' => 1.0, 886# 'IO::Stringy' => 0, 887# 'LWP::UserAgent' => 0, 888# 'DateTime' => 0, 889# 'DateTime::Duration' => 0, 890# 'DateTime::TimeZone' => 0, 891# 'HTML::Entities' => 1.27, 892# 'XML::LibXML' => 0, }, 893# }, 894 895 { name => 'tv_grab_uk_tvguide', 896 blurb => 'Grabber for UK and Ireland using TV Guide website', 897 exes => [ 'grab/uk_tvguide/tv_grab_uk_tvguide' ], 898 share_files => { 899 'grab/uk_tvguide/tv_grab_uk_tvguide.map.conf' 900 => 'tv_grab_uk_tvguide/tv_grab_uk_tvguide.map.conf', 901 }, 902 prereqs => { 'HTTP::Cache::Transparent' => 1.0, 903 'HTML::TreeBuilder' => 0, 904 'DateTime' => 0, 905 'Date::Parse' => 0, 906 'Encode' => 0, 907 'URI::Escape' => 0, 908 'File::Path' => 0, 909 'Data::Dumper' => 0, }, 910 }, 911 912 { name => 'tv_grab_zz_sdjson', 913 blurb => '$$ Grabber for schedulesDirect.org SD-JSON service (many countries)', 914 exes => [ 'grab/zz_sdjson/tv_grab_zz_sdjson' ], 915 prereqs => { 'DateTime' => 0, 916 'Digest::SHA' => 0, 917 'JSON' => 0, 918 'LWP::Protocol::https' => 0, 919 'LWP::UserAgent' => 0, 920 'Storable' => 0, 921 'Try::Tiny' => 0, }, 922 }, 923 924 { name => 'tv_grab_zz_sdjson_sqlite', 925 blurb => '$$ Grabber for schedulesDirect.org SD-JSON service (many countries, using sqlite)', 926 exes => [ 'grab/zz_sdjson_sqlite/tv_grab_zz_sdjson_sqlite' ], 927 prereqs => { 'Encode' => 0, 928 'JSON' => 0, 929 'Digest::SHA' => 0, 930 'File::Basename' => 0, 931 'File::Which' => 0, 932 'File::HomeDir' => 0, 933 'File::Path' => 0, 934 'DateTime' => 0, 935 'DateTime::TimeZone' => 0, 936 'DateTime::Format::ISO8601' => 0, 937 'DateTime::Format::SQLite' => 0, 938 'List::MoreUtils' => 0, 939 'DBI' => 0, 940 'DBD::SQLite' => 0, 941 'Scalar::Util' => 0, 942 'Data::Dumper' => 0, 943 'LWP::UserAgent::Determined' => 0, }, 944 }, 945 946 947# honir 2015-03-05 hasn't worked since 2014-11-19 - source site permanently broken 948# { name => 'tv_grab_za', 949# blurb => 'Grabber for South Africa', 950# exes => [ 'grab/za/tv_grab_za' ], 951# prereqs => { 'HTML::TreeBuilder' => 0, 952# 'HTML::Entities' => 1.27 } }, 953 954 { name => 'tv_check', 955 blurb => 'Program to report exceptions and changes in a schedule', 956 exes => [ 'choose/tv_check/tv_check' ], 957 docs => [ qw(choose/tv_check/README.tv_check 958 choose/tv_check/tv_check_doc.html 959 choose/tv_check/tv_check_doc.jpg 960 ) ], 961 prereqs => { 'Tk' => 0, 962 'Tk::TableMatrix' => 0, } 963 }, 964 965 { name => 'tv_grab_combiner', 966 blurb => 'Grabber that combines data from other grabbers', 967 exes => [ 'grab/combiner/tv_grab_combiner' ], 968 prereqs => { 'XML::LibXML' => 0, }, 969 }, 970 971 { name => 'tv_pick_cgi', 972 blurb => 'CGI program to filter listings (to install manually)', 973 prereqs => { 'CGI' => 0, }, 974 type => 'run', 975 }, 976 977 ); 978 979# Now we need to prompt about each optional component. The style of 980# prompting, though not the code, is based on SOAP::Lite. I would 981# like to add '--noprompt' and '--with tv_grab_nl' options to help 982# automated package building, but I haven't implemented that yet. 983# 984 985# For each component work out whether its prereqs are installed and 986# store the result in {missing} - either false, or a hashref. 987# 988foreach my $info (@opt_components) { 989 my $name = $info->{name}; 990 my %modules_missing; 991 our %module_prereqs; 992 local *module_prereqs = $info->{prereqs} || {}; 993 foreach (sort keys %module_prereqs) { 994 my $ver = $module_prereqs{$_}; 995 next if test_module($_, $ver)->[0] eq 'OK'; 996 warn "strange, module prereq $_ mentioned twice" 997 if defined $modules_missing{$_}; 998 $modules_missing{$_} = $ver; 999 } 1000 1001 our @special_prereqs; 1002 my %special_missing; 1003 local *special_prereqs = $info->{special_prereqs} || {}; 1004 foreach (@special_prereqs) { 1005 my ($sub, $name, $ver, $friendly_ver) = @$_; 1006 next if test_special($sub, $ver)->[0] eq 'OK'; 1007 warn "strange, special prereq $name mentioned twice" 1008 if defined $special_missing{$name}; 1009 $special_missing{$name} = $friendly_ver; 1010 } 1011 1012 my %missing = (%modules_missing, %special_missing); 1013 if (not keys %missing) { 1014 $info->{missing} = 0; 1015 } 1016 else { 1017 $info->{missing} = \%missing; 1018 } 1019} 1020 1021if (not defined $opt_components) { 1022 # Generate a default configuration that installs as much as possible. 1023 print STDERR <<END 1024 1025Choose which optional components of xmltv you want to install. The 1026XMLTV.pm library and the filter programs such as tv_grep and tv_sort 1027are installed by default; here you choose grabbers for different 1028countries and front-ends for managing listings. 1029 1030END 1031; 1032 1033 my %by_name; 1034 foreach (@opt_components) { 1035 $by_name{$_->{name}} = $_; 1036 $_->{exclude} = 0; # default if not mentioned 1037 } 1038 1039 if (defined $opt_exclude) { 1040 foreach (split /,/, $opt_exclude) { 1041 my $i = $by_name{$_}; 1042 die "unknown component $_\n" if not $i; 1043 $i->{exclude} = 1; 1044 } 1045 } 1046 1047 my $width = 0; 1048 foreach my $info (@opt_components) { 1049 my $w = length("$info->{blurb} ($info->{name})"); 1050 $width = $w if $w > $width; 1051 } 1052 foreach my $info (@opt_components) { 1053 my $missing = $info->{missing}; 1054 my $s = "$info->{blurb} ($info->{name})"; 1055 1056 # Guess a default value for {install} based on whether 1057 # prerequisites were found. 1058 # 1059 $info->{install} = 1;(not $info->{exclude}) && ($opt_yes || not $info->{missing}); 1060 1061 print STDERR ($s, ' ' x (1 + $width - length $s), 1062 $info->{install} ? '[yes]' : '[no]', 1063 "\n"); 1064 } 1065 print STDERR "\n"; 1066 if (1 or not ask(0, 'Do you want to proceed with this configuration?', 1)) { 1067 # Need to set {install} for each component by prompting. 1068 foreach my $info (@opt_components) { 1069 my $missing = $info->{missing}; 1070 my $name = $info->{name}; 1071 print STDERR "\n* $info->{blurb} ($name)\n\n"; 1072 if ($missing) { 1073 print STDERR "These dependencies are missing for $name:\n\n"; 1074 foreach (sort keys %$missing) { 1075 print STDERR "$_"; 1076 my $min_ver = $missing->{$_}; 1077 if ($min_ver) { 1078 print STDERR " (version $min_ver or higher)"; 1079 } 1080 print STDERR "\n"; 1081 } 1082 print STDERR "\n"; 1083 } 1084 1085 my $msg; 1086 my $type = $info->{type}; 1087 if (not defined $type or $type eq 'install') { 1088 $msg = "Do you wish to install $name?"; 1089 } elsif ($type eq 'run') { 1090 $msg = "Do you plan to run $name?"; 1091 } else { 1092 die; 1093 } 1094 1095 $info->{install} = 1; 1096 # ask(0, $msg, not $missing); 1097 } 1098 } 1099} 1100else { 1101 my @to_install = split /\s+/, $opt_components; 1102 my %by_name; 1103 foreach (@opt_components) { 1104 $by_name{$_->{name}} = $_; 1105 $_->{install} = 0; # default if not mentioned 1106 } 1107 foreach (@to_install) { 1108 my $i = $by_name{$_}; 1109 die "unknown component $_\n" if not $i; 1110 $i->{install} = 1; 1111 } 1112} 1113 1114foreach my $info (@opt_components) { 1115 next if not $info->{install}; 1116 push @exes, @{$info->{exes}} if $info->{exes}; 1117 push @docs, @{$info->{docs}} if $info->{docs}; 1118 %pm = (%pm, %{$info->{pm}}) if $info->{pm}; 1119 %prereqs = (%prereqs, %{$info->{prereqs}}) if $info->{prereqs}; 1120 %pl_files = (%pl_files, %{$info->{pl_files}}) if $info->{pl_files}; 1121 %share_files = (%share_files, %{$info->{share_files}}) 1122 if $info->{share_files}; 1123 push @to_clean, @{$info->{to_clean}} if $info->{to_clean}; 1124 push @deps, @{$info->{deps}} if $info->{deps}; 1125 push @grab_need_share, @{$info->{grab_need_share}} 1126 if $info->{grab_need_share}; 1127} 1128 1129my $warned_uninstall_broken = 1; 1130 1131 1132# Test the installed version of a module. 1133# 1134# Parameters: 1135# Name of module 1136# Version required, or 0 for don't care 1137# 1138# Returns a tuple of two scalars: the first scalar is one of 1139# 1140# OK - a recent enough version is installed. 1141# NOT_INSTALLED - the module is not installed. 1142# FAILED - the second scalar contains an error message. 1143# TOO_OLD - the second scalar contains the version found. 1144# 1145sub test_module( $$ ) { 1146 my ($mod, $minver) = @_; 1147 die if not defined $mod; die if not defined $minver; 1148 eval "require $mod"; 1149 if ($@) { 1150 # This if-test is separate to suppress spurious 'Use of 1151 # uninitialized value in numeric lt (<)' warning. 1152 # 1153 if ($@ ne '') { 1154 if ($@ =~ /^Can\'t locate \S+\.pm in \@INC/) { 1155 return [ 'NOT_INSTALLED', undef ]; 1156 } 1157 else { 1158 chomp (my $msg = $@); 1159 return [ 'FAILED', $msg ]; 1160 } 1161 } 1162 } 1163 1164 my $ver = $mod->VERSION; 1165 if ($minver ne '0') { 1166 return [ 'TOO_OLD', undef ] if not defined $ver; 1167 return [ 'TOO_OLD', $ver ] if $ver lt $minver; 1168 } 1169 1170 return [ 'OK', undef ]; 1171} 1172 1173# Run a subroutine and check that its output has the correct version. 1174# 1175# Parameters: 1176# code reference to run 1177# minumum version 1178# 1179# The code ref should return undef meaning 'package not present' or 1180# else a version number. 1181# 1182# Returns as for test_module() (but 'FAILED' not an option). 1183# 1184sub test_special( $$ ) { 1185 my ($sub, $minver) = @_; 1186 my $ver = $sub->(); 1187 return [ 'NOT_INSTALLED', undef ] if not defined $ver; 1188 if ($minver ne '0') { 1189 return [ 'TOO_OLD', undef ] if not defined $ver; 1190 return [ 'TOO_OLD', $ver ] if $ver lt $minver; 1191 } 1192 return [ 'OK', undef ]; 1193} 1194 1195# MakeMaker's warning message can be intimidating, check ourselves 1196# first. We warn about missing 'recommended' modules but don't abort 1197# because of them. 1198# 1199my $err = 0; 1200foreach my $p ((sort keys %prereqs), (sort keys %recommended)) { 1201 my $required = (defined $prereqs{$p}); 1202 my $verbed = $required ? 'required' : 'recommended'; 1203 my $Verbed = uc(substr($verbed, 0, 1)) . substr($verbed, 1); 1204 my $minver = $required ? $prereqs{$p} : $recommended{$p}; 1205 die "bad minver for $p" if not defined $minver; 1206 my ($r, $more) = @{test_module($p, $minver)}; 1207 if ($r eq 'OK') { 1208 # Installed and recent enough. 1209 } 1210 elsif ($r eq 'NOT_INSTALLED') { 1211 print STDERR "Module $p seems not to be installed.\n"; 1212 print(($minver ? "$p $minver" : $p), " is $verbed.\n"); 1213 ++ $err if $required; 1214 } 1215 elsif ($r eq 'FAILED') { 1216 print STDERR "$Verbed module $p failed to load: $more\n"; 1217 print(($minver ? "$p $minver" : $p), " is $verbed.\n"); 1218 ++ $err if $required; 1219 } 1220 elsif ($r eq 'TOO_OLD') { 1221 if (defined $more) { 1222 print STDERR "$p-$minver is $verbed, but $more is installed\n"; 1223 } 1224 else { 1225 print STDERR "$p-$minver is $verbed, but an unknown version is installed\n"; 1226 } 1227 ++ $err if $required; 1228 } 1229 else { die } 1230} 1231if ($err) { 1232 if ($opt_strictdeps) { 1233 die "Required modules missing. Makefile will not be created.\n"; 1234 } 1235 else { 1236 warn "Required modules missing, 'make' is unlikely to work\n"; 1237 } 1238} 1239 1240WriteMakefile 1241 ( 1242 'NAME' => 'XMLTV', 1243 # No VERSION_FROM, it's set in this file 1244 'EXE_FILES' => \@exes, 1245 'PL_FILES' => \%pl_files, 1246 'PM' => \%pm, 1247 'PREREQ_PM' => \%prereqs, 1248 # No special parameters for 'make clean' or 'make dist' 1249 ); 1250 1251 1252sub MY::constants { 1253 package MY; 1254 my $inherited = shift->SUPER::constants(@_); 1255 die if not keys %::extra_constants; 1256 foreach (sort keys %::extra_constants) { 1257 $inherited .= "$_ = $::extra_constants{$_}\n"; 1258 } 1259 return $inherited; 1260} 1261sub MY::install { 1262 package MY; 1263 my $inherited = shift->SUPER::install(@_); 1264 1265 # Decided that 'plaindoc_install' should be directly under 1266 # 'install', not under the misleadingly named 'doc_install'. 1267 # 1268 my %extra_deps = (install => [ 'plaindoc_install', 'share_install' ]); 1269 foreach my $t (keys %extra_deps) { 1270 foreach my $d (@{$extra_deps{$t}}) { 1271 $inherited =~ s/^(\s*$t\s+::\s.+)/$1 $d/m or die; 1272 } 1273 } 1274 1275 foreach (qw(plaindoc share)) { 1276 my $target = $_ . '_install'; 1277 my $uc = uc; 1278 1279 my $inst_var = "INST_$uc"; 1280 my $extra = <<END 1281# Add code to create the directory under blib/. 1282\$($inst_var)/.exists :: \$(PERL_INC)/perl.h 1283 \@\$(MKPATH) \$($inst_var) 1284 \@\$(EQUALIZE_TIMESTAMP) \$(PERL_INC)/perl.h \$($inst_var)/.exists 1285 -\@\$(CHMOD) \$(PERM_RWX) \$($inst_var) 1286 1287# Create a target to install to the final location. 1288$target :: 1289 \@echo Installing contents of \$(INST_$uc) into \$(INSTALL$uc) 1290 \@\$(MOD_INSTALL) \\ 1291 \$(INST_$uc) \$(INSTALL$uc) 1292 1293END 1294; 1295 $extra =~ s/ {8}/\t/g; 1296 $inherited .= $extra; 1297 } 1298 1299 # Remove existing non-working 'uninstall' target. 1300 $inherited =~ s!^uninstall\s::?.*?\n\t+.*$!!m; 1301 $inherited =~ s!^uninstall\s:.*$!!m; 1302 1303 # For each *_install create a corresponding _uninstall. 1304 my $targets = ::targets($inherited); 1305 foreach (qw(pure_perl_install pure_site_install plaindoc_install share_install)) { 1306 die "no $_ in: $inherited" if not defined $targets->{$_}; 1307 my @t = @{$targets->{$_}}; # make a copy 1308 my $done = 0; 1309 foreach (@t) { 1310 if (s/\@\$\(MOD_INSTALL\)/\$(PERL) -I. -MUninstall -e "uninstall(\@ARGV)"/) { 1311 $done = 1; 1312 last; 1313 } 1314 s/Installing contents of (\S+) into (\S+)/Removing contents of $1 from $2/; 1315 } 1316 if (not $done) { 1317 print STDERR "couldn't find \@\$(MOD_INSTALL) in target $_, uninstall may not work\n" 1318 unless $warned_uninstall_broken; 1319 } 1320 (my $new_target = $_) =~ s/install$/uninstall/ or die; 1321 foreach ("\n\n$new_target ::\n", @t) { 1322 $inherited .= $_; 1323 } 1324 } 1325 $inherited .= 'pure_uninstall :: pure_$(INSTALLDIRS)_uninstall' . "\n"; 1326 $inherited .= 'uninstall :: all pure_uninstall plaindoc_uninstall share_uninstall' . "\n"; 1327 1328 # Add a target for a Windows distribution. Note this is 1329 # singlequoted and then we substitute one variable by hand! 1330 # 1331 $inherited .= q{ 1332 1333xmltv.exe :: $(EXE_FILES) lib/exe_wrap.pl lib/exe_opt.pl 1334 echo $(EXE_FILES) >exe_files.txt 1335 perl lib/exe_opt.pl $(VERSION) >exe_opt.txt 1336 echo -lib $(INST_ARCHLIB) --lib $(INST_LIB) >>exe_opt.txt 1337 echo -add "$(EXE_FILES)" >>exe_opt.txt 1338 echo -bind exe_files.txt >>exe_opt.txt 1339 echo -exe xmltv.exe >>exe_opt.txt 1340 perlapp @exe_opt.txt lib/exe_wrap.pl 1341 $(RM_F) exe_files.txt 1342 $(RM_F) exe_opt.txt 1343 1344windows_dist :: 1345 @perl -e "if (-e '$location') { print STDERR qq[To build a Windows distribution, please rerun Makefile.PL with\nPREFIX set to a new (nonexistent) directory then 'make windows_dist'.\n(Remember that only absolute paths work properly with MakeMaker.)\n]; exit 1 }" 1346 @perl -e 'print "Have you updated doc/README.win32 for this release? "; exit 1 unless <STDIN> =~ /^[yY]/' 1347 $(MAKE) install 1348 perl -MExtUtils::Command -e mv $(INSTALLPLAINDOC) $location/doc/ 1349 perl -MExtUtils::Command -e rm_r $location/share/doc 1350 perl -MExtUtils::Command -e mkpath $location/doc/man 1351 # Generate plain text documentation from pod. 1352 perl -e "chdir 'blib/script' or die; foreach (<*>) { system qq'pod2text <\$$_ >$location/doc/man/\$$_.txt' }" 1353 # Remove 'real' manual pages, not needed on Windows. 1354 perl -MExtUtils::Command -e rm_rf $location/man $location/man 1355 # My MakeMaker creates this dud directory. 1356 perl -MExtUtils::Command -e rm_rf $location/5.8.0 1357 rmdir $location/share/doc 1358 # Generate Date::Manip docs by filtering perldoc output. The 1359 # use of temp files instead of pipes is so set -e works properly. 1360 # 1361 echo Extracting part of Date::Manip manual page into $location/doc/man/date_formats.txt 1362 echo "This is an extract from the documentation of Perl's Date::Manip module," >>$location/doc/man/date_formats.txt 1363 echo "describing the different format strings that may be used for dates." >>$location/doc/man/date_formats.txt 1364 echo "Bear in mind that depending on your Windows version you will need to" >>$location/doc/man/date_formats.txt 1365 echo "quote the % characters on the command line somehow (see README.win32)." >>$location/doc/man/date_formats.txt 1366 echo "" >>$location/doc/man/date_formats.txt 1367 perldoc -u Date::Manip >$location/doc/man/date_formats.txt.tmp 1368 perl -ne "BEGIN { print qq'\n=pod\n\n' } print if (/^The format options are:/ .. /^=/) and not /^=/" <$location/doc/man/date_formats.txt.tmp >$location/doc/man/date_formats.txt.tmp.1 1369 pod2text <$location/doc/man/date_formats.txt.tmp.1 >>$location/doc/man/date_formats.txt 1370 perl -MExtUtils::Command -e rm_f $location/doc/man/date_formats.txt.tmp* 1371 # Don't use $(INSTALLBIN), it seems to disregard PREFIX passed 1372 # to 'make'. 1373 # 1374 perl -MExtUtils::Command -e rm_rf $location/bin/ $location/lib/ $(INSTMANDIR) $(INSTALLMAN3DIR) 1375 perl -MExtUtils::Command -e cp xmltv.dtd $location 1376 perl -MExtUtils::Command -e cp xmltv-lineups.xsd $location 1377 perl -MExtUtils::Command -e cp ChangeLog $location/ChangeLog.txt 1378 # The following command will not be necessary when the source 1379 # tree was checked out on a DOSish system. It may not even 1380 # work properly when run on a DOSish system - should check. 1381 # 1382 # (Simulation in perl of find | xargs; there's probably a 1383 # better way but I'm too lazy to find it.) 1384 # 1385 perl -MFile::Find -e "find(sub { print qq[\\$$File::Find::name\n] if -f and not /[.]jpg/ }, '$location')" | perl -e 'chomp(@ARGV = (@ARGV, <STDIN>)); exec @ARGV' perl -i -pe 'BEGIN { binmode STDIN } s/\r*\n*$$/\r\n/' 1386 perl -MExtUtils::Command -e mv $location/doc/README* $location 1387 perl -MExtUtils::Command -e mv $location/README.win32 $location/README.txt 1388 @echo 1389 @echo Part of a Windows distribution tree has been made in $location/. 1390 @echo Now copy in the executables! 1391 1392}; 1393 $inherited =~ s/\$location/$location/g or die; 1394 1395 return $inherited; 1396} 1397 1398# Extend installbin() to put doc and share under blib/. 1399sub MY::installbin { 1400 package MY; 1401 my $inherited = shift->SUPER::installbin(@_); 1402 1403 # Add a target for each documentation file. 1404 my %doc_files; 1405 foreach (@::docs) { 1406 $doc_files{$_} = File::Basename::basename($_); 1407 } 1408 1409 my %new_filetypes = (plaindoc => \%doc_files, share => \%share_files); 1410 my %seen_dir; 1411 foreach my $filetype (sort keys %new_filetypes) { 1412 my $uc = uc $filetype; 1413 our %files; local *files = $new_filetypes{$filetype}; 1414 foreach my $src (sort keys %files) { 1415 my $inst_pos = $files{$src}; 1416 my $extra = ''; 1417 1418 # The directory containing this file in blib/ needs to be created. 1419 my @dirs = split m!/!, $inst_pos; pop @dirs; 1420 foreach (0 .. $#dirs) { 1421 my $dir = join('/', @dirs[0 .. $_]); 1422 my $parent = join('/', @dirs[0 .. $_-1]); 1423 next if $seen_dir{$dir}++; 1424 die if (length $parent and not $seen_dir{$parent}); 1425 my $parent_exists = "\$(INST_$uc)/$parent/.exists"; 1426 $parent_exists =~ tr!/!/!s; 1427 $extra .= <<END 1428\$(INST_$uc)/$dir/.exists :: \$(PERL_INC)/perl.h $parent_exists 1429 \@\$(MKPATH) \$(INST_$uc)/$dir 1430 \@\$(EQUALIZE_TIMESTAMP) \$(PERL_INC)/perl.h \$(INST_$uc)/$dir/.exists 1431 -\@\$(CHMOD) \$(PERM_RWX) \$(INST_$uc)/$dir 1432END 1433; 1434 } 1435 my $dir_exists = "\$(INST_$uc)/" . join('/', @dirs) . '/.exists'; 1436 $dir_exists =~ tr!/!/!s; 1437 1438 $extra .= <<END 1439\$(INST_$uc)/$inst_pos: $src Makefile $dir_exists 1440 \@\$(RM_F) \$(INST_$uc)/$inst_pos 1441 perl -MExtUtils::Command -e cp $src \$(INST_$uc)/$inst_pos 1442 -\@\$(CHMOD) \$(PERM_RW) \$(INST_$uc)/$inst_pos 1443END 1444; 1445 $extra =~ s/ {8}/\t/g; 1446 $inherited .= $extra; 1447 } 1448 1449 # These targets need to be added to pure_all, using a new target 1450 # pure_$filetype. 1451 # 1452 $inherited =~ s/^(\s*pure_all\s+::\s.+)/$1 pure_$filetype/m 1453 or die "no pure_all in: $inherited"; 1454 $inherited .= "pure_$filetype :: "; 1455 foreach (sort keys %files) { 1456 my $inst_pos = $files{$_}; 1457 $inherited .= "\$(INST_$uc)/$inst_pos "; 1458 } 1459 $inherited .= "\n\t\@\$(NOOP)\n"; 1460 1461 # And realclean should remove them, by calling realclean_$filetype. 1462 $inherited =~ s/^(\s*realclean\s+::\s[^\\]+)/$1 realclean_$filetype /m or die; 1463 $inherited .= "realclean_$filetype ::\n\t\$(RM_F) "; 1464 foreach (sort keys %files) { 1465 my $inst_pos = $files{$_}; 1466 $inherited .= "\$(INST_$uc)/$inst_pos "; 1467 } 1468 $inherited .= "\n"; 1469 } 1470 1471 return $inherited; 1472} 1473 1474# 'make clean' doesn't remove generated files from *.PL (see posting 1475# to makemaker@perl.org). Fix it. 1476# 1477sub MY::clean { 1478 package MY; 1479 my $inherited = shift->SUPER::clean(@_); 1480 $inherited =~ s/\s+$//; 1481 $inherited .= "\n\t-\$(RM_F) $_\n" foreach @to_clean; 1482 return $inherited; 1483} 1484 1485sub MY::processPL { 1486 package MY; 1487 my $inherited = shift->SUPER::processPL(@_); 1488 1489 # Add some exra dependencies. 1490 my ($k, $v); 1491 while (@deps) { 1492 ($k, $v, @deps) = @deps; 1493 $inherited =~ s!^(\s*$k\s+::\s.+)!"$1 " . join(' ', @$v)!me 1494 or die "no $k in: $inherited"; 1495 } 1496 1497 # And some of the .in generators need the share/ directory passed 1498 # as an extra argument. This is the location in the installed 1499 # system, not that where files are being copied, so $(PREFIX) but 1500 # no $(DESTDIR). 1501 # 1502 foreach (@grab_need_share) { 1503 $inherited =~ 1504 s<(grab/$_/tv_grab_$_.PL grab/$_/tv_grab_$_)\s*$> 1505 <$1 \$(PREFIX)/share/xmltv>m 1506 or die "no call to $_.PL in: $inherited"; 1507 } 1508 1509 foreach (@need_share) { 1510 $inherited =~ 1511 s<($_.PL $_)\s*$> 1512 <$1 \$(PREFIX)/share/xmltv>m 1513 or die "no call to $_.PL in: $inherited"; 1514 } 1515 1516 1517 return $inherited; 1518} 1519 1520sub MY::makefile { 1521 package MY; 1522 my $inherited = shift->SUPER::makefile(@_); 1523 return $inherited; 1524} 1525 1526# Fix filename of some generated manpages. 1527sub MY::manifypods { 1528 package MY; 1529 for (my $inherited = shift->SUPER::manifypods(@_)) { 1530 foreach my $s (qw(Augment Grab_XML Configure::Writer Configure Data::Recursive::Encode Date GUI Gunzip Options PreferredMethod Summarize Supplement ValidateFile ValidateGrabber Version)) { 1531 s!\$\(INST_MAN3DIR\)/(?:grab::|)$s[.]\$\(MAN3EXT\)!"\$(INST_MAN3DIR)/XMLTV::$s.\$(MAN3EXT)"!; 1532 s!\$\(INSTALLMAN3DIR\)/$s.\$\(MAN3EXT\)!"\$(INSTALLMAN3DIR)/XMLTV::$s.\$(MAN3EXT)"!; 1533 } 1534 return $_; 1535 } 1536} 1537 1538# Split a section of makefile into targets. 1539sub targets( $ ) { 1540 my @lines = split /\n/, shift; 1541 $_ .= "\n" foreach @lines; 1542 my %r; 1543 my $curr_target; 1544 foreach (@lines) { 1545 if (/^(\S+)\s+:/) { 1546 # Beginning of a new target. 1547 my $name = $1; 1548 die "target $name seen twice" if defined $r{$name}; 1549 $r{$name} = $curr_target = []; 1550 } 1551 elsif (/^\s+/ and defined $curr_target) { 1552 # Commands for the target. 1553 push @$curr_target, $_; 1554 } 1555 elsif (/^$/) { 1556 # Blank lines are legal in a target definition 1557 } 1558 elsif (/^\s*(?:\#.*)?$/) { 1559 undef $curr_target; 1560 } 1561 else { 1562 chomp; 1563 die "bad makefile line: '$_'"; 1564 } 1565 } 1566 return \%r; 1567} 1568