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