1#!/usr/bin/perl 2# SPDX-License-Identifier: GPL-2.0-or-later 3use strict; 4 5# Copyright (c) 2017-2020 Mauro Carvalho Chehab <mchehab@kernel.org> 6# 7 8my $prefix = "./"; 9$prefix = "$ENV{'srctree'}/" if ($ENV{'srctree'}); 10 11my $conf = $prefix . "Documentation/conf.py"; 12my $requirement_file = $prefix . "Documentation/sphinx/requirements.txt"; 13my $virtenv_prefix = "sphinx_"; 14 15# 16# Static vars 17# 18 19my %missing; 20my $system_release; 21my $need = 0; 22my $optional = 0; 23my $need_symlink = 0; 24my $need_sphinx = 0; 25my $need_venv = 0; 26my $need_virtualenv = 0; 27my $rec_sphinx_upgrade = 0; 28my $install = ""; 29my $virtenv_dir = ""; 30my $python_cmd = ""; 31my $min_version; 32 33# 34# Command line arguments 35# 36 37my $pdf = 1; 38my $virtualenv = 1; 39my $version_check = 0; 40 41# 42# List of required texlive packages on Fedora and OpenSuse 43# 44 45my %texlive = ( 46 'amsfonts.sty' => 'texlive-amsfonts', 47 'amsmath.sty' => 'texlive-amsmath', 48 'amssymb.sty' => 'texlive-amsfonts', 49 'amsthm.sty' => 'texlive-amscls', 50 'anyfontsize.sty' => 'texlive-anyfontsize', 51 'atbegshi.sty' => 'texlive-oberdiek', 52 'bm.sty' => 'texlive-tools', 53 'capt-of.sty' => 'texlive-capt-of', 54 'cmap.sty' => 'texlive-cmap', 55 'ecrm1000.tfm' => 'texlive-ec', 56 'eqparbox.sty' => 'texlive-eqparbox', 57 'eu1enc.def' => 'texlive-euenc', 58 'fancybox.sty' => 'texlive-fancybox', 59 'fancyvrb.sty' => 'texlive-fancyvrb', 60 'float.sty' => 'texlive-float', 61 'fncychap.sty' => 'texlive-fncychap', 62 'footnote.sty' => 'texlive-mdwtools', 63 'framed.sty' => 'texlive-framed', 64 'luatex85.sty' => 'texlive-luatex85', 65 'multirow.sty' => 'texlive-multirow', 66 'needspace.sty' => 'texlive-needspace', 67 'palatino.sty' => 'texlive-psnfss', 68 'parskip.sty' => 'texlive-parskip', 69 'polyglossia.sty' => 'texlive-polyglossia', 70 'tabulary.sty' => 'texlive-tabulary', 71 'threeparttable.sty' => 'texlive-threeparttable', 72 'titlesec.sty' => 'texlive-titlesec', 73 'ucs.sty' => 'texlive-ucs', 74 'upquote.sty' => 'texlive-upquote', 75 'wrapfig.sty' => 'texlive-wrapfig', 76); 77 78# 79# Subroutines that checks if a feature exists 80# 81 82sub check_missing(%) 83{ 84 my %map = %{$_[0]}; 85 86 foreach my $prog (sort keys %missing) { 87 my $is_optional = $missing{$prog}; 88 89 # At least on some LTS distros like CentOS 7, texlive doesn't 90 # provide all packages we need. When such distros are 91 # detected, we have to disable PDF output. 92 # 93 # So, we need to ignore the packages that distros would 94 # need for LaTeX to work 95 if ($is_optional == 2 && !$pdf) { 96 $optional--; 97 next; 98 } 99 100 if ($is_optional) { 101 print "Warning: better to also install \"$prog\".\n"; 102 } else { 103 print "ERROR: please install \"$prog\", otherwise, build won't work.\n"; 104 } 105 if (defined($map{$prog})) { 106 $install .= " " . $map{$prog}; 107 } else { 108 $install .= " " . $prog; 109 } 110 } 111 112 $install =~ s/^\s//; 113} 114 115sub add_package($$) 116{ 117 my $package = shift; 118 my $is_optional = shift; 119 120 $missing{$package} = $is_optional; 121 if ($is_optional) { 122 $optional++; 123 } else { 124 $need++; 125 } 126} 127 128sub check_missing_file($$$) 129{ 130 my $files = shift; 131 my $package = shift; 132 my $is_optional = shift; 133 134 for (@$files) { 135 return if(-e $_); 136 } 137 138 add_package($package, $is_optional); 139} 140 141sub findprog($) 142{ 143 foreach(split(/:/, $ENV{PATH})) { 144 return "$_/$_[0]" if(-x "$_/$_[0]"); 145 } 146} 147 148sub check_program($$) 149{ 150 my $prog = shift; 151 my $is_optional = shift; 152 153 return $prog if findprog($prog); 154 155 add_package($prog, $is_optional); 156} 157 158sub check_perl_module($$) 159{ 160 my $prog = shift; 161 my $is_optional = shift; 162 163 my $err = system("perl -M$prog -e 1 2>/dev/null /dev/null"); 164 return if ($err == 0); 165 166 add_package($prog, $is_optional); 167} 168 169sub check_python_module($$) 170{ 171 my $prog = shift; 172 my $is_optional = shift; 173 174 return if (!$python_cmd); 175 176 my $err = system("$python_cmd -c 'import $prog' 2>/dev/null /dev/null"); 177 return if ($err == 0); 178 179 add_package($prog, $is_optional); 180} 181 182sub check_rpm_missing($$) 183{ 184 my @pkgs = @{$_[0]}; 185 my $is_optional = $_[1]; 186 187 foreach my $prog(@pkgs) { 188 my $err = system("rpm -q '$prog' 2>/dev/null >/dev/null"); 189 add_package($prog, $is_optional) if ($err); 190 } 191} 192 193sub check_pacman_missing($$) 194{ 195 my @pkgs = @{$_[0]}; 196 my $is_optional = $_[1]; 197 198 foreach my $prog(@pkgs) { 199 my $err = system("pacman -Q '$prog' 2>/dev/null >/dev/null"); 200 add_package($prog, $is_optional) if ($err); 201 } 202} 203 204sub check_missing_tex($) 205{ 206 my $is_optional = shift; 207 my $kpsewhich = findprog("kpsewhich"); 208 209 foreach my $prog(keys %texlive) { 210 my $package = $texlive{$prog}; 211 if (!$kpsewhich) { 212 add_package($package, $is_optional); 213 next; 214 } 215 my $file = qx($kpsewhich $prog); 216 add_package($package, $is_optional) if ($file =~ /^\s*$/); 217 } 218} 219 220sub get_sphinx_fname() 221{ 222 my $fname = "sphinx-build"; 223 return $fname if findprog($fname); 224 225 $fname = "sphinx-build-3"; 226 if (findprog($fname)) { 227 $need_symlink = 1; 228 return $fname; 229 } 230 231 return ""; 232} 233 234sub check_sphinx() 235{ 236 my $rec_version; 237 my $cur_version; 238 239 open IN, $conf or die "Can't open $conf"; 240 while (<IN>) { 241 if (m/^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]/) { 242 $min_version=$1; 243 last; 244 } 245 } 246 close IN; 247 248 die "Can't get needs_sphinx version from $conf" if (!$min_version); 249 250 open IN, $requirement_file or die "Can't open $requirement_file"; 251 while (<IN>) { 252 if (m/^\s*Sphinx\s*==\s*([\d\.]+)$/) { 253 $rec_version=$1; 254 last; 255 } 256 } 257 close IN; 258 259 die "Can't get recommended sphinx version from $requirement_file" if (!$min_version); 260 261 $virtenv_dir = $virtenv_prefix . $rec_version; 262 263 my $sphinx = get_sphinx_fname(); 264 if ($sphinx eq "") { 265 $need_sphinx = 1; 266 return; 267 } 268 269 open IN, "$sphinx --version 2>&1 |" or die "$sphinx returned an error"; 270 while (<IN>) { 271 if (m/^\s*sphinx-build\s+([\d\.]+)(\+\/[\da-f]+)?$/) { 272 $cur_version=$1; 273 last; 274 } 275 # Sphinx 1.2.x uses a different format 276 if (m/^\s*Sphinx.*\s+([\d\.]+)$/) { 277 $cur_version=$1; 278 last; 279 } 280 } 281 close IN; 282 283 die "$sphinx didn't return its version" if (!$cur_version); 284 285 if ($cur_version lt $min_version) { 286 printf "ERROR: Sphinx version is %s. It should be >= %s (recommended >= %s)\n", 287 $cur_version, $min_version, $rec_version;; 288 $need_sphinx = 1; 289 return; 290 } 291 292 if ($cur_version lt $rec_version) { 293 printf "Sphinx version %s\n", $cur_version; 294 print "Warning: It is recommended at least Sphinx version $rec_version.\n"; 295 $rec_sphinx_upgrade = 1; 296 return; 297 } 298 299 # On version check mode, just assume Sphinx has all mandatory deps 300 exit (0) if ($version_check); 301} 302 303# 304# Ancillary subroutines 305# 306 307sub catcheck($) 308{ 309 my $res = ""; 310 $res = qx(cat $_[0]) if (-r $_[0]); 311 return $res; 312} 313 314sub which($) 315{ 316 my $file = shift; 317 my @path = split ":", $ENV{PATH}; 318 319 foreach my $dir(@path) { 320 my $name = $dir.'/'.$file; 321 return $name if (-x $name ); 322 } 323 return undef; 324} 325 326# 327# Subroutines that check distro-specific hints 328# 329 330sub give_debian_hints() 331{ 332 my %map = ( 333 "python-sphinx" => "python3-sphinx", 334 "sphinx_rtd_theme" => "python3-sphinx-rtd-theme", 335 "ensurepip" => "python3-venv", 336 "virtualenv" => "virtualenv", 337 "dot" => "graphviz", 338 "convert" => "imagemagick", 339 "Pod::Usage" => "perl-modules", 340 "xelatex" => "texlive-xetex", 341 "rsvg-convert" => "librsvg2-bin", 342 ); 343 344 if ($pdf) { 345 check_missing_file(["/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"], 346 "fonts-dejavu", 2); 347 348 check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc", 349 "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", 350 "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc"], 351 "fonts-noto-cjk", 2); 352 } 353 354 check_program("dvipng", 2) if ($pdf); 355 check_missing(\%map); 356 357 return if (!$need && !$optional); 358 printf("You should run:\n\n\tsudo apt-get install $install\n"); 359} 360 361sub give_redhat_hints() 362{ 363 my %map = ( 364 "python-sphinx" => "python3-sphinx", 365 "sphinx_rtd_theme" => "python3-sphinx_rtd_theme", 366 "virtualenv" => "python3-virtualenv", 367 "dot" => "graphviz", 368 "convert" => "ImageMagick", 369 "Pod::Usage" => "perl-Pod-Usage", 370 "xelatex" => "texlive-xetex-bin", 371 "rsvg-convert" => "librsvg2-tools", 372 ); 373 374 my @fedora26_opt_pkgs = ( 375 "graphviz-gd", # Fedora 26: needed for PDF support 376 ); 377 378 my @fedora_tex_pkgs = ( 379 "texlive-collection-fontsrecommended", 380 "texlive-collection-latex", 381 "texlive-xecjk", 382 "dejavu-sans-fonts", 383 "dejavu-serif-fonts", 384 "dejavu-sans-mono-fonts", 385 ); 386 387 # 388 # Checks valid for RHEL/CentOS version 7.x. 389 # 390 my $old = 0; 391 my $rel; 392 $rel = $1 if ($system_release =~ /release\s+(\d+)/); 393 394 if (!($system_release =~ /Fedora/)) { 395 $map{"virtualenv"} = "python-virtualenv"; 396 397 if ($rel && $rel < 8) { 398 $old = 1; 399 $pdf = 0; 400 401 printf("Note: texlive packages on RHEL/CENTOS <= 7 are incomplete. Can't support PDF output\n"); 402 printf("If you want to build PDF, please read:\n"); 403 printf("\thttps://www.systutorials.com/241660/how-to-install-tex-live-on-centos-7-linux/\n"); 404 } 405 } else { 406 if ($rel && $rel < 26) { 407 $old = 1; 408 } 409 } 410 if (!$rel) { 411 printf("Couldn't identify release number\n"); 412 $old = 1; 413 $pdf = 0; 414 } 415 416 if ($pdf) { 417 check_missing_file(["/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc"], 418 "google-noto-sans-cjk-ttc-fonts", 2); 419 } 420 421 check_rpm_missing(\@fedora26_opt_pkgs, 2) if ($pdf && !$old); 422 check_rpm_missing(\@fedora_tex_pkgs, 2) if ($pdf); 423 check_missing_tex(2) if ($pdf); 424 check_missing(\%map); 425 426 return if (!$need && !$optional); 427 428 if (!$old) { 429 # dnf, for Fedora 18+ 430 printf("You should run:\n\n\tsudo dnf install -y $install\n"); 431 } else { 432 # yum, for RHEL (and clones) or Fedora version < 18 433 printf("You should run:\n\n\tsudo yum install -y $install\n"); 434 } 435} 436 437sub give_opensuse_hints() 438{ 439 my %map = ( 440 "python-sphinx" => "python3-sphinx", 441 "sphinx_rtd_theme" => "python3-sphinx_rtd_theme", 442 "virtualenv" => "python3-virtualenv", 443 "dot" => "graphviz", 444 "convert" => "ImageMagick", 445 "Pod::Usage" => "perl-Pod-Usage", 446 "xelatex" => "texlive-xetex-bin", 447 ); 448 449 # On Tumbleweed, this package is also named rsvg-convert 450 $map{"rsvg-convert"} = "rsvg-view" if (!($system_release =~ /Tumbleweed/)); 451 452 my @suse_tex_pkgs = ( 453 "texlive-babel-english", 454 "texlive-caption", 455 "texlive-colortbl", 456 "texlive-courier", 457 "texlive-dvips", 458 "texlive-helvetic", 459 "texlive-makeindex", 460 "texlive-metafont", 461 "texlive-metapost", 462 "texlive-palatino", 463 "texlive-preview", 464 "texlive-times", 465 "texlive-zapfchan", 466 "texlive-zapfding", 467 ); 468 469 $map{"latexmk"} = "texlive-latexmk-bin"; 470 471 # FIXME: add support for installing CJK fonts 472 # 473 # I tried hard, but was unable to find a way to install 474 # "Noto Sans CJK SC" on openSUSE 475 476 check_rpm_missing(\@suse_tex_pkgs, 2) if ($pdf); 477 check_missing_tex(2) if ($pdf); 478 check_missing(\%map); 479 480 return if (!$need && !$optional); 481 printf("You should run:\n\n\tsudo zypper install --no-recommends $install\n"); 482} 483 484sub give_mageia_hints() 485{ 486 my %map = ( 487 "python-sphinx" => "python3-sphinx", 488 "sphinx_rtd_theme" => "python3-sphinx_rtd_theme", 489 "virtualenv" => "python3-virtualenv", 490 "dot" => "graphviz", 491 "convert" => "ImageMagick", 492 "Pod::Usage" => "perl-Pod-Usage", 493 "xelatex" => "texlive", 494 "rsvg-convert" => "librsvg2", 495 ); 496 497 my @tex_pkgs = ( 498 "texlive-fontsextra", 499 ); 500 501 $map{"latexmk"} = "texlive-collection-basic"; 502 503 my $packager_cmd; 504 my $noto_sans; 505 if ($system_release =~ /OpenMandriva/) { 506 $packager_cmd = "dnf install"; 507 $noto_sans = "noto-sans-cjk-fonts"; 508 @tex_pkgs = ( "texlive-collection-fontsextra" ); 509 } else { 510 $packager_cmd = "urpmi"; 511 $noto_sans = "google-noto-sans-cjk-ttc-fonts"; 512 } 513 514 515 if ($pdf) { 516 check_missing_file(["/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc", 517 "/usr/share/fonts/TTF/NotoSans-Regular.ttf"], 518 $noto_sans, 2); 519 } 520 521 check_rpm_missing(\@tex_pkgs, 2) if ($pdf); 522 check_missing(\%map); 523 524 return if (!$need && !$optional); 525 printf("You should run:\n\n\tsudo $packager_cmd $install\n"); 526} 527 528sub give_arch_linux_hints() 529{ 530 my %map = ( 531 "sphinx_rtd_theme" => "python-sphinx_rtd_theme", 532 "virtualenv" => "python-virtualenv", 533 "dot" => "graphviz", 534 "convert" => "imagemagick", 535 "xelatex" => "texlive-bin", 536 "latexmk" => "texlive-core", 537 "rsvg-convert" => "extra/librsvg", 538 ); 539 540 my @archlinux_tex_pkgs = ( 541 "texlive-core", 542 "texlive-latexextra", 543 "ttf-dejavu", 544 ); 545 check_pacman_missing(\@archlinux_tex_pkgs, 2) if ($pdf); 546 547 if ($pdf) { 548 check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc"], 549 "noto-fonts-cjk", 2); 550 } 551 552 check_missing(\%map); 553 554 return if (!$need && !$optional); 555 printf("You should run:\n\n\tsudo pacman -S $install\n"); 556} 557 558sub give_gentoo_hints() 559{ 560 my %map = ( 561 "sphinx_rtd_theme" => "dev-python/sphinx_rtd_theme", 562 "virtualenv" => "dev-python/virtualenv", 563 "dot" => "media-gfx/graphviz", 564 "convert" => "media-gfx/imagemagick", 565 "xelatex" => "dev-texlive/texlive-xetex media-fonts/dejavu", 566 "rsvg-convert" => "gnome-base/librsvg", 567 ); 568 569 check_missing_file(["/usr/share/fonts/dejavu/DejaVuSans.ttf"], 570 "media-fonts/dejavu", 2) if ($pdf); 571 572 if ($pdf) { 573 check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf", 574 "/usr/share/fonts/noto-cjk/NotoSerifCJK-Regular.ttc"], 575 "media-fonts/noto-cjk", 2); 576 } 577 578 check_missing(\%map); 579 580 return if (!$need && !$optional); 581 582 printf("You should run:\n\n"); 583 584 my $imagemagick = "media-gfx/imagemagick svg png"; 585 my $cairo = "media-gfx/graphviz cairo pdf"; 586 my $portage_imagemagick = "/etc/portage/package.use/imagemagick"; 587 my $portage_cairo = "/etc/portage/package.use/graphviz"; 588 589 if (qx(grep imagemagick $portage_imagemagick 2>/dev/null) eq "") { 590 printf("\tsudo su -c 'echo \"$imagemagick\" > $portage_imagemagick'\n") 591 } 592 if (qx(grep graphviz $portage_cairo 2>/dev/null) eq "") { 593 printf("\tsudo su -c 'echo \"$cairo\" > $portage_cairo'\n"); 594 } 595 596 printf("\tsudo emerge --ask $install\n"); 597 598} 599 600sub check_distros() 601{ 602 # Distro-specific hints 603 if ($system_release =~ /Red Hat Enterprise Linux/) { 604 give_redhat_hints; 605 return; 606 } 607 if ($system_release =~ /CentOS/) { 608 give_redhat_hints; 609 return; 610 } 611 if ($system_release =~ /Scientific Linux/) { 612 give_redhat_hints; 613 return; 614 } 615 if ($system_release =~ /Oracle Linux Server/) { 616 give_redhat_hints; 617 return; 618 } 619 if ($system_release =~ /Fedora/) { 620 give_redhat_hints; 621 return; 622 } 623 if ($system_release =~ /Ubuntu/) { 624 give_debian_hints; 625 return; 626 } 627 if ($system_release =~ /Debian/) { 628 give_debian_hints; 629 return; 630 } 631 if ($system_release =~ /openSUSE/) { 632 give_opensuse_hints; 633 return; 634 } 635 if ($system_release =~ /Mageia/) { 636 give_mageia_hints; 637 return; 638 } 639 if ($system_release =~ /OpenMandriva/) { 640 give_mageia_hints; 641 return; 642 } 643 if ($system_release =~ /Arch Linux/) { 644 give_arch_linux_hints; 645 return; 646 } 647 if ($system_release =~ /Gentoo/) { 648 give_gentoo_hints; 649 return; 650 } 651 652 # 653 # Fall-back to generic hint code for other distros 654 # That's far from ideal, specially for LaTeX dependencies. 655 # 656 my %map = ( 657 "sphinx-build" => "sphinx" 658 ); 659 check_missing_tex(2) if ($pdf); 660 check_missing(\%map); 661 print "I don't know distro $system_release.\n"; 662 print "So, I can't provide you a hint with the install procedure.\n"; 663 print "There are likely missing dependencies.\n"; 664} 665 666# 667# Common dependencies 668# 669 670sub deactivate_help() 671{ 672 printf "\nIf you want to exit the virtualenv, you can use:\n"; 673 printf "\tdeactivate\n"; 674} 675 676sub check_needs() 677{ 678 # Check if Sphinx is already accessible from current environment 679 check_sphinx(); 680 681 if ($system_release) { 682 print "Detected OS: $system_release.\n\n"; 683 } else { 684 print "Unknown OS\n\n"; 685 } 686 687 print "To upgrade Sphinx, use:\n\n" if ($rec_sphinx_upgrade); 688 689 # Check python command line, trying first python3 690 $python_cmd = findprog("python3"); 691 $python_cmd = check_program("python", 0) if (!$python_cmd); 692 693 # Check the type of virtual env, depending on Python version 694 if ($python_cmd) { 695 if ($virtualenv) { 696 my $tmp = qx($python_cmd --version 2>&1); 697 if ($tmp =~ m/(\d+\.)(\d+\.)/) { 698 if ($1 >= 3 && $2 >= 3) { 699 $need_venv = 1; # python 3.3 or upper 700 } else { 701 $need_virtualenv = 1; 702 } 703 if ($1 < 3) { 704 # Complain if it finds python2 (or worse) 705 printf "Warning: python$1 support is deprecated. Use it with caution!\n"; 706 } 707 } else { 708 die "Warning: couldn't identify $python_cmd version!"; 709 } 710 } else { 711 add_package("python-sphinx", 0); 712 } 713 } 714 715 # Set virtualenv command line, if python < 3.3 716 my $virtualenv_cmd; 717 if ($need_virtualenv) { 718 $virtualenv_cmd = findprog("virtualenv-3"); 719 $virtualenv_cmd = findprog("virtualenv-3.5") if (!$virtualenv_cmd); 720 if (!$virtualenv_cmd) { 721 check_program("virtualenv", 0); 722 $virtualenv_cmd = "virtualenv"; 723 } 724 } 725 726 # Check for needed programs/tools 727 check_perl_module("Pod::Usage", 0); 728 check_program("make", 0); 729 check_program("gcc", 0); 730 check_python_module("sphinx_rtd_theme", 1) if (!$virtualenv); 731 check_program("dot", 1); 732 check_program("convert", 1); 733 734 # Extra PDF files - should use 2 for is_optional 735 check_program("xelatex", 2) if ($pdf); 736 check_program("rsvg-convert", 2) if ($pdf); 737 check_program("latexmk", 2) if ($pdf); 738 739 if ($need_sphinx || $rec_sphinx_upgrade) { 740 check_python_module("ensurepip", 0) if ($need_venv); 741 } 742 743 # Do distro-specific checks and output distro-install commands 744 check_distros(); 745 746 if (!$python_cmd) { 747 if ($need == 1) { 748 die "Can't build as $need mandatory dependency is missing"; 749 } elsif ($need) { 750 die "Can't build as $need mandatory dependencies are missing"; 751 } 752 } 753 754 # Check if sphinx-build is called sphinx-build-3 755 if ($need_symlink) { 756 printf "\tsudo ln -sf %s /usr/bin/sphinx-build\n\n", 757 which("sphinx-build-3"); 758 } 759 760 # NOTE: if the system has a too old Sphinx version installed, 761 # it will recommend installing a newer version using virtualenv 762 763 if ($need_sphinx || $rec_sphinx_upgrade) { 764 my $min_activate = "$ENV{'PWD'}/${virtenv_prefix}${min_version}/bin/activate"; 765 my @activates = glob "$ENV{'PWD'}/${virtenv_prefix}*/bin/activate"; 766 767 @activates = sort {$b cmp $a} @activates; 768 769 if ($need_sphinx && scalar @activates > 0 && $activates[0] ge $min_activate) { 770 printf "\nNeed to activate a compatible Sphinx version on virtualenv with:\n"; 771 printf "\t. $activates[0]\n"; 772 deactivate_help(); 773 exit (1); 774 } else { 775 my $rec_activate = "$virtenv_dir/bin/activate"; 776 777 if ($need_venv) { 778 printf "\t$python_cmd -m venv $virtenv_dir\n"; 779 } else { 780 printf "\t$virtualenv_cmd $virtenv_dir\n"; 781 } 782 printf "\t. $rec_activate\n"; 783 printf "\tpip install -r $requirement_file\n"; 784 deactivate_help(); 785 786 $need++ if (!$rec_sphinx_upgrade); 787 } 788 } 789 printf "\n"; 790 791 print "All optional dependencies are met.\n" if (!$optional); 792 793 if ($need == 1) { 794 die "Can't build as $need mandatory dependency is missing"; 795 } elsif ($need) { 796 die "Can't build as $need mandatory dependencies are missing"; 797 } 798 799 print "Needed package dependencies are met.\n"; 800} 801 802# 803# Main 804# 805 806while (@ARGV) { 807 my $arg = shift(@ARGV); 808 809 if ($arg eq "--no-virtualenv") { 810 $virtualenv = 0; 811 } elsif ($arg eq "--no-pdf"){ 812 $pdf = 0; 813 } elsif ($arg eq "--version-check"){ 814 $version_check = 1; 815 } else { 816 print "Usage:\n\t$0 <--no-virtualenv> <--no-pdf> <--version-check>\n\n"; 817 print "Where:\n"; 818 print "\t--no-virtualenv\t- Recommend installing Sphinx instead of using a virtualenv\n"; 819 print "\t--version-check\t- if version is compatible, don't check for missing dependencies\n"; 820 print "\t--no-pdf\t- don't check for dependencies required to build PDF docs\n\n"; 821 exit -1; 822 } 823} 824 825# 826# Determine the system type. There's no standard unique way that would 827# work with all distros with a minimal package install. So, several 828# methods are used here. 829# 830# By default, it will use lsb_release function. If not available, it will 831# fail back to reading the known different places where the distro name 832# is stored 833# 834 835$system_release = qx(lsb_release -d) if which("lsb_release"); 836$system_release =~ s/Description:\s*// if ($system_release); 837$system_release = catcheck("/etc/system-release") if !$system_release; 838$system_release = catcheck("/etc/redhat-release") if !$system_release; 839$system_release = catcheck("/etc/lsb-release") if !$system_release; 840$system_release = catcheck("/etc/gentoo-release") if !$system_release; 841 842# This seems more common than LSB these days 843if (!$system_release) { 844 my %os_var; 845 if (open IN, "cat /etc/os-release|") { 846 while (<IN>) { 847 if (m/^([\w\d\_]+)=\"?([^\"]*)\"?\n/) { 848 $os_var{$1}=$2; 849 } 850 } 851 $system_release = $os_var{"NAME"}; 852 if (defined($os_var{"VERSION_ID"})) { 853 $system_release .= " " . $os_var{"VERSION_ID"} if (defined($os_var{"VERSION_ID"})); 854 } else { 855 $system_release .= " " . $os_var{"VERSION"}; 856 } 857 } 858} 859$system_release = catcheck("/etc/issue") if !$system_release; 860$system_release =~ s/\s+$//; 861 862check_needs; 863