#!/usr/bin/env perl use 5.004; use strict; use warnings; use File::Spec; sub shell ($@); sub env ($$); sub cd ($); sub auto_complete ($); sub usage ($); my (@make_cmds, @make_install_cmds); my $ngx_dir; my @modules = ( [http_iconv => 'iconv-nginx-module', 'disabled'], [http_echo => 'echo-nginx-module'], [http_xss => 'xss-nginx-module'], [ndk => 'ngx_devel_kit'], [http_set_misc => 'set-misc-nginx-module'], [http_form_input => 'form-input-nginx-module'], [http_encrypted_session => 'encrypted-session-nginx-module'], [http_drizzle => 'drizzle-nginx-module'], [http_postgres => 'drizzle-nginx-module', 'disabled'], [http_lua => 'lua-nginx-module'], [http_headers_more => 'headers-more-nginx-module'], [http_srcache => 'srcache-nginx-module'], [http_array_var => 'array-var-nginx-module'], [http_memc => 'memc-nginx-module'], [http_upstream_keepalive => 'upstream-keepalive-nginx-module'], [http_auth_request => 'auth-request-nginx-module'], [http_rds_json => 'rds-json-nginx-module'], ); my $without_resty_mods_regex; { my $s = '^--without-(' . join('|', map { $_->[0] } grep { @$_ == 2 && $_->[0] =~ /^http_/ } @modules ) . ')_module$'; #warn "without regex: $s"; $without_resty_mods_regex = qr/$s/; } my $with_resty_mods_regex; { my $s = '^--with-(' . join('|', map { $_->[0] } grep { @$_ == 3 && $_->[0] =~ /^http_/ } @modules ) . ')_module$'; #warn "with regex: $s"; $with_resty_mods_regex = qr/$s/; } my $prefix = '/usr/local/openresty'; my %resty_opts; my $dry_run; my @ngx_rpaths; my @ngx_opts; for my $opt (@ARGV) { if ($opt eq '--dry-run') { $dry_run = 1; next; } if ($opt =~ /^--prefix=(.*)/) { $prefix = $1; } elsif ($opt eq '--with-debug') { $resty_opts{debug} = 1; } elsif ($opt eq '--help') { usage 0; } elsif ($opt =~ $without_resty_mods_regex) { die "No $1\n"; $resty_opts{"no_http_$1"} = 1; } elsif ($opt eq '--without-ngx_devel_kit_module') { $resty_opts{no_ndk} = 1; } elsif ($opt =~ $with_resty_mods_regex) { $resty_opts{"http_$1"} = 1; } elsif ($opt eq '--with-luajit') { $resty_opts{luajit} = 1; } elsif ($opt eq '--with-http_ssl_module') { $resty_opts{http_ssl} = 1; push @ngx_opts, $opt; } elsif ($opt eq '--without-http_ssl_module') { $resty_opts{no_http_ssl} = 1; } elsif ($opt =~ /^--\w.*/) { push @ngx_opts, $opt; } else { die "Invalid option $opt\n"; } } my $ngx_prefix = "$prefix/nginx"; my $cmd = "./configure --prefix=$ngx_prefix" . build_resty_opts(\%resty_opts) . (@ngx_rpaths ? " \\\n --with-ld-opt='-Wl,-rpath=" . join(":", @ngx_rpaths) . "'" : "") . (@ngx_opts ? " \\\n " . join(" ", @ngx_opts) : ""); ; shell $cmd, $dry_run; push @make_cmds, "cd build/$ngx_dir && " . "\$(MAKE)"; push @make_install_cmds, "cd build/$ngx_dir && " . "\$(MAKE) install DESTDIR=\$(DESTDIR)"; cd '../..'; # to the root #die "pwd: " .. `pwd`; gen_makefile(); sub env ($$) { my ($name, $val) = @_; print "export $name='$val'\n"; $ENV{$name} = $val; } sub shell ($@) { my ($cmd, $dry_run) = @_; print "$cmd\n"; unless ($dry_run) { system($cmd) == 0 or die "failed to run command @_\n"; } } sub auto_complete ($) { my $name = shift; my @dirs = glob "$name-*" or die "No source directory found for $name\n"; if (@dirs > 1) { die "More than one hits for $name: @dirs\n"; } return $dirs[0]; } sub cd ($) { my $dir = shift; print("cd $dir\n"); chdir $dir or die "failed to cd $dir: $!\n"; } sub build_resty_opts { my $opts = shift; if ($opts->{no_ndk}) { for my $name (qw(lua set_misc iconv lz_session form_input array_var)) { if (! $opts->{"no_http_$name"}) { warn "WARNING: ngx_http_${name}_module is automatically disabled ", "because ngx_devel_kit_module is disabled.\n"; $opts->{"no_http_$name"} = 1; } } } if (! $opts->{luajit} && ! $opts->{no_http_lua}) { $opts->{lua} = 1; } if (! $opts->{no_http_drizzle}) { $opts->{libdrizzle} = 1; } if ($opts->{no_http_ssl} && $opts->{http_ssl}) { die "--with-http_ssl_module conflicts with --without-http_ssl_module\n"; } if (! $opts->{no_http_ssl} && ! $opts->{http_ssl}) { $opts->{http_ssl} = 1; push @ngx_opts, '--with-http_ssl_module'; } my $opts_line = ''; if ($opts->{debug}) { $opts_line .= " \\\n --with-cc-opt='-O0' \\\n --with-debug"; } else { $opts_line .= " \\\n --with-cc-opt='-O2'"; } if (-d 'build') { system("rm -rf build"); } if (-f 'build') { die "build/ directory already exists\n"; } shell "cp -r bundle/ build/"; cd 'build'; # build 3rd-party C libraries if required if ($opts->{luajit}) { my $luajit_src = auto_complete 'LuaJIT'; my $luajit_prefix = "$prefix/luajit"; my $luajit_root = File::Spec->rel2abs("luajit-root"); if (-d $luajit_root) { shell "rm -rf $luajit_root"; } mkdir $luajit_root or die "create create directory luajit-root: $!\n"; cd $luajit_src; shell "make PREFIX=$luajit_prefix", $dry_run; shell "make install PREFIX=$luajit_prefix DESTDIR=$luajit_root", $dry_run; push @make_cmds, "cd build/$luajit_src && " . "\$(MAKE) PREFIX=$luajit_prefix"; push @make_install_cmds, "cd build/$luajit_src && " . "\$(MAKE) install PREFIX=$luajit_prefix DESTDIR=\$(DESTDIR)"; env LUAJIT_LIB => "$luajit_root$luajit_prefix/lib"; env LUAJIT_INC => "$luajit_root$luajit_prefix/include/luajit-2.0"; push @ngx_rpaths, "$luajit_prefix/lib"; cd '..'; } elsif ($opts->{lua}) { # build stdandard lua my $lua_src = glob('lua-5.*'); if (!defined $lua_src) { die "No lua5 found"; } my $lua_prefix = "$prefix/lua"; my $lua_root = File::Spec->rel2abs("lua-root"); if (-d $lua_root) { shell "rm -rf $lua_root"; } mkdir $lua_root or die "create create directory lua-root: $!\n"; cd $lua_src; shell "make linux", $dry_run; shell "make install INSTALL_TOP=$lua_root$lua_prefix", $dry_run; env LUA_LIB => "$lua_root$lua_prefix/lib"; env LUA_INC => "$lua_root$lua_prefix/include"; push @make_cmds, "cd build/$lua_src && \$(MAKE) linux"; push @make_install_cmds, "cd build/$lua_src && " . "\$(MAKE) install INSTALL_TOP=\$(DESTDIR)$lua_prefix"; cd '..'; } # prepare nginx configure line $ngx_dir = auto_complete "nginx"; cd $ngx_dir; for my $mod (@modules) { my ($name, $prefix, $attr) = @$mod; if ($attr && $attr eq 'disabled') { next if not $opts->{"$name"}; } else { next if $opts->{"no_$name"}; } my $dir = auto_complete "../$prefix"; $opts_line .= " \\\n --add-module=$dir"; } return $opts_line; } sub usage ($) { my $retval = shift; my $msg = <<'_EOC_'; --help this message --prefix=PATH set the installation prefix --with-debug enable the debugging logging and also enable -O0 _EOC_ my $opt_max_len = length " --without-ngx_devel_kit_module "; #warn "opt max len: $opt_max_len"; my $with_resty_opts = ''; for my $mod (@modules) { my $name = $mod->[0]; if ($name =~ /^http_/) { if (@$mod == 2) { my $opt = " --without-${name}_module"; $msg .= $opt; my $n = $opt_max_len - length $opt; if ($n > 0) { $msg .= " " x $n; } else { $msg .= "\n" . (" " x $opt_max_len); } $msg .= "disable ngx_${name}_module\n"; } else { my $opt = " --with-${name}_module"; $with_resty_opts .= $opt; my $n = $opt_max_len - length $opt; if ($n > 0) { $with_resty_opts .= " " x $n; } else { $with_resty_opts .= "\n" . (" " x $opt_max_len); } $with_resty_opts .= "enable ngx_${name}_module\n"; } } } $msg .= <<'_EOC_'; --without-ngx_devel_kit_module disable ngx_devel_kit_module --without-http_ssl_module disable ngx_http_ssl_module _EOC_ $msg .= $with_resty_opts; $msg .= <<'_EOC_'; --with-luajit enable LuaJIT 2.0 Options directly inherited from nginx --sbin-path=PATH set path to the nginx binary file --conf-path=PATH set path to the nginx.conf file --error-log-path=PATH set path to the error log --pid-path=PATH set path to nginx.pid file --lock-path=PATH set path to nginx.lock file --user=USER set non-privilege user for the worker processes --group=GROUP set non-privilege group for the worker processes --builddir=DIR set the build directory --with-rtsig_module enable rtsig module --with-select_module enable select module --without-select_module disable select module --with-poll_module enable poll module --without-poll_module disable poll module --with-file-aio enable file aio support --with-ipv6 enable ipv6 support --with-http_realip_module enable ngx_http_realip_module --with-http_addition_module enable ngx_http_addition_module --with-http_xslt_module enable ngx_http_xslt_module --with-http_image_filter_module enable ngx_http_image_filter_module --with-http_geoip_module enable ngx_http_geoip_module --with-http_sub_module enable ngx_http_sub_module --with-http_dav_module enable ngx_http_dav_module --with-http_flv_module enable ngx_http_flv_module --with-http_gzip_static_module enable ngx_http_gzip_static_module --with-http_random_index_module enable ngx_http_random_index_module --with-http_secure_link_module enable ngx_http_secure_link_module --with-http_degradation_module enable ngx_http_degradation_module --with-http_stub_status_module enable ngx_http_stub_status_module --without-http_charset_module disable ngx_http_charset_module --without-http_gzip_module disable ngx_http_gzip_module --without-http_ssi_module disable ngx_http_ssi_module --without-http_userid_module disable ngx_http_userid_module --without-http_access_module disable ngx_http_access_module --without-http_auth_basic_module disable ngx_http_auth_basic_module --without-http_autoindex_module disable ngx_http_autoindex_module --without-http_geo_module disable ngx_http_geo_module --without-http_map_module disable ngx_http_map_module --without-http_split_clients_module disable ngx_http_split_clients_module --without-http_referer_module disable ngx_http_referer_module --without-http_rewrite_module disable ngx_http_rewrite_module --without-http_proxy_module disable ngx_http_proxy_module --without-http_fastcgi_module disable ngx_http_fastcgi_module --without-http_uwsgi_module disable ngx_http_uwsgi_module --without-http_scgi_module disable ngx_http_scgi_module --without-http_memcached_module disable ngx_http_memcached_module --without-http_limit_zone_module disable ngx_http_limit_zone_module --without-http_limit_req_module disable ngx_http_limit_req_module --without-http_empty_gif_module disable ngx_http_empty_gif_module --without-http_browser_module disable ngx_http_browser_module --without-http_upstream_ip_hash_module disable ngx_http_upstream_ip_hash_module --with-http_perl_module enable ngx_http_perl_module --with-perl_modules_path=PATH set path to the perl modules --with-perl=PATH set path to the perl binary --http-log-path=PATH set path to the http access log --http-client-body-temp-path=PATH set path to the http client request body temporary files --http-proxy-temp-path=PATH set path to the http proxy temporary files --http-fastcgi-temp-path=PATH set path to the http fastcgi temporary files --http-uwsgi-temp-path=PATH set path to the http uwsgi temporary files --http-scgi-temp-path=PATH set path to the http scgi temporary files --without-http disable HTTP server --without-http-cache disable HTTP cache --with-mail enable POP3/IMAP4/SMTP proxy module --with-mail_ssl_module enable ngx_mail_ssl_module --without-mail_pop3_module disable ngx_mail_pop3_module --without-mail_imap_module disable ngx_mail_imap_module --without-mail_smtp_module disable ngx_mail_smtp_module --with-google_perftools_module enable ngx_google_perftools_module --with-cpp_test_module enable ngx_cpp_test_module --add-module=PATH enable an external module --with-cc=PATH set path to C compiler --with-cpp=PATH set path to C preprocessor --with-cc-opt=OPTIONS set additional options for C compiler --with-ld-opt=OPTIONS set additional options for linker --with-cpu-opt=CPU build for specified CPU, the valid values: pentium, pentiumpro, pentium3, pentium4, athlon, opteron, sparc32, sparc64, ppc64 --without-pcre disable PCRE library usage --with-pcre force PCRE library usage --with-pcre=DIR set path to PCRE library sources --with-pcre-opt=OPTIONS set additional options for PCRE building --with-md5=DIR set path to md5 library sources --with-md5-opt=OPTIONS set additional options for md5 building --with-md5-asm use md5 assembler sources --with-sha1=DIR set path to sha1 library sources --with-sha1-opt=OPTIONS set additional options for sha1 building --with-sha1-asm use sha1 assembler sources --with-zlib=DIR set path to zlib library sources --with-zlib-opt=OPTIONS set additional options for zlib building --with-zlib-asm=CPU use zlib assembler sources optimized for specified CPU, the valid values: pentium, pentiumpro --with-libatomic force libatomic_ops library usage --with-libatomic=DIR set path to libatomic_ops library sources --with-openssl=DIR set path to OpenSSL library sources --with-openssl-opt=OPTIONS set additional options for OpenSSL building --dry-run dry running the configure, for testing only _EOC_ if ($retval == 0) { print $msg; exit 0; } warn $msg; exit $retval; } sub gen_makefile { open my $out, ">Makefile" or die "Cannot open Makefile for writing: $!\n"; print $out ".PHONY: all install\n\n"; print $out "all:\n\t" . join("\n\t", @make_cmds) . "\n\n"; print $out "install:\n\t" . join("\n\t", @make_install_cmds) . "\n\n"; print $out "clean:\n\trm -rf build\n"; close $out; }