use strict;
use warnings;
use Getopt::Long;
use File::Path;
use File::Basename qw(dirname);
use Cwd qw(getcwd realpath);
use FindBin qw($Bin $RealBin);
my @HELP_DESCRIPTIONS = (
[ "enable-debug", "",
"Create a debug build",
"%d", \(my $DEBUG = 0) ],
[ "with-ninja", "s",
"Generate Ninja Makefiles",
"%s", \(my $USE_NINJA = "") ],
[ "prefix", "s",
"installation prefix",
"%s", \(my $PREFIX = "/usr/local") ],
[ "disable-tools", "",
"Don't build tools",
"%d", \(my $NO_TOOLS = 0)],
[ "disable-tests", "",
"Don't build tests",
"%d", \(my $NO_TESTS = 0)],
[ "with-libuv", "s",
"Path to LIBUV installation",
"%s", \(my $LIBUV_ROOT = "")],
[ "with-libev", "s",
"Path to LIBEV installation",
"%s", \(my $LIBEV_ROOT = "")],
[ "with-libevent", "s",
"Path to LIBEVENT installation",
"%s", \(my $LIBEVENT_ROOT = "")],
[ "with-cmake", "s",
"Executable to use as cmake",
"%s", \(my $CMAKE_EXE = "cmake")],
[ "with-openssl", "s",
"Path to OpenSSL installation",
"%s", \(my $OPENSSL_ROOT = "")],
[ "with-snappy", "s",
"Path to snappy installation",
"%s", \(my $SNAPPY_ROOT = "")],
[ "disable-snappy", "",
"Do not build static snappy",
"%d", \(my $NO_SNAPPY = 0)],
[ "enable-snappy", "",
"Enable experimental snappy support",
"%d", \(my $ENABLE_SNAPPY = 0)],
[ "enable-static-snappy", "",
"Build the bundled snappy and do not link against the system version",
"%d", \(my $STATIC_SNAPPY = 0) ],
[ "disable-plugins", "",
"Disable building of external plugins",
"%d", \(my $NO_PLUGINS = 0)],
[ "disable-cxx", "",
"Disable C++ targets",
"%d", \(my $NO_CXX = 0) ],
[ "disable-couchbasemock", "",
"Don't run tests with Mock",
"%d", \(my $NO_MOCK = 0) ],
[ "enable-maintainer-mode", "",
"Maintainer mode. Everything is strict",
"%d", \(my $MAINTAINER_MODE = 0)],
[ "enable-fat-binary", "",
"Build universal binaries on OS X",
"%d", \(my $OSX_UNIVERSAL_BUILD = 0)],
[ "cmake-verbose", "",
"Verbose CMake output",
"%d", \(my $CMAKE_VERBOSE = 0)],
[ "host", "s",
"Set host target for Win32 cross compilation",
"%s", \(my $CMAKE_HOST = "")],
[ "enable-static", "",
"Build static libraries",
"%d", \(my $STATIC_LIBS = 0)],
[ "enable-embedded-libevent-plugin", "",
"Embed the libevent plugin into the library's core",
"%d", \(my $EMBED_LIBEVENT_PLUGIN = 0) ],
[ "cc", "s",
"C Compiler",
"%s", \(my $CC = "") ],
[ "cxx", "s",
"C++ Compiler",
"%s", \(my $CXX = "") ],
[ "disable-ssl", "",
"Do not build SSL support",
"%d", \(my $NO_SSL = 0)],
[ "enable-asan", "",
"Enable LLVM AddressSanitizer support",
"%d", \(my $LCB_USE_ASAN = 0)],
[ "enable-coverage", "",
"Compile with code coverage instrumentation",
"%d", \(my $LCB_USE_COVERAGE = 0)],
[ "enable-examples", "",
"Build examples",
"%s", \(my $BUILD_EXAMPLES = 0)],
[ "build-dir", "s",
"Directory to build in",
"%s", \(my $BUILD_DIR = "build") ],
[ "help", "",
"This message", "%s", \(my $WANT_HELP = 0) ]
);
my @HELPLINES = ();
my %GETOPT_ARGS = ();
foreach my $optdesc (@HELP_DESCRIPTIONS) {
my ($name, $vfmt, $desc, $deflfmt, $vref) = @$optdesc;
my $go_key = $name;
if ($vfmt) {
$go_key .= "=$vfmt";
}
$GETOPT_ARGS{$go_key} = $vref;
}
GetOptions(%GETOPT_ARGS);
if ($WANT_HELP) {
printf("configure.pl ... options\n");
foreach my $optdesc (@HELP_DESCRIPTIONS) {
my ($name, $vfmt, $desc, $fmt, $deflref) = @$optdesc;
printf(" --%-20s", $name);
if (length($name) > 18) {
printf("\n");
printf("%-20s%s\n","", $desc);
} else {
printf("%s.", $desc);
}
printf(" Default=".$fmt."\n", ${$deflref});
}
exit(0);
}
my $origdir = getcwd();
my $srcdir = realpath("$RealBin/..");
if ($origdir eq $srcdir) {
printf("Detected in-source build. Making '$BUILD_DIR' directory\n");
mkpath($BUILD_DIR);
chdir($BUILD_DIR);
}
if ($NO_CXX) {
$NO_TESTS=1;
$NO_TOOLS=1;
}
my @CM_OPTIONS = ();
my @VARNAMES = (qw(CC CXX CFLAGS CPPFLAGS CXXFLAGS LDFLAGS LIBS));
my %ENVOPTIONS = ();
foreach my $var (@VARNAMES) {
$ENVOPTIONS{$var} = $ENV{$var};
}
foreach my $arg (@ARGV) {
my ($k,$v) = $arg =~ m/([^=]+)=(.*)/;
unless ($k && $v && exists $ENVOPTIONS{$k}) {
die("Invalid variable $arg");
}
$ENVOPTIONS{$k} = $v;
}
my $flags_common = "";
my $flags_cxx = "";
my $flags_cc = "";
if ($ENVOPTIONS{CC}) { $CC = $ENVOPTIONS{CC}; }
if ($ENVOPTIONS{CXX}) { $CXX = $ENVOPTIONS{CXX}; }
if ($ENVOPTIONS{CPPFLAGS}) {
$flags_common = $ENVOPTIONS{CPPFLAGS};
}
$flags_cxx = $flags_common;
$flags_cc = $flags_common;
if ($ENVOPTIONS{CFLAGS}) {
$flags_cc .= " " . $ENVOPTIONS{CFLAGS};
}
if ($ENVOPTIONS{CXXFLAGS}) {
$flags_cxx .= " ".$ENVOPTIONS{CXXFLAGS};
}
if ($flags_cc) {
push @CM_OPTIONS, "-DCMAKE_C_FLAGS=$flags_cc";
}
if ($flags_cxx) {
push @CM_OPTIONS, "-DCMAKE_CXX_FLAGS=$flags_cxx";
}
if ($ENVOPTIONS{LDFLAGS}) {
my $flags = $ENVOPTIONS{LDFLAGS};
foreach my $var (qw(EXE_LINKER_FLAGS SHARED_LINKER_FLAGS)) {
push @CM_OPTIONS, "-DCMAKE_${var}=$flags";
}
}
if ($ENVOPTIONS{LIBS}) {
warn("Don't know how to convert autotools 'LIBS' into CMake");
}
if ($DEBUG) {
push @CM_OPTIONS, "-DCMAKE_BUILD_TYPE=DEBUG";
} else {
push @CM_OPTIONS, "-DCMAKE_BUILD_TYPE=RelWithDebInfo"
}
if ($PREFIX) {
push @CM_OPTIONS, "-DCMAKE_INSTALL_PREFIX=$PREFIX";
}
if ($NO_TESTS) {
push @CM_OPTIONS, "-DLCB_NO_TESTS=1";
}
if ($NO_TOOLS) {
push @CM_OPTIONS, "-DLCB_NO_TOOLS=1";
}
if ($NO_PLUGINS) {
push @CM_OPTIONS, "-DLCB_NO_PLUGINS=1";
}
if ($LIBUV_ROOT) {
push @CM_OPTIONS, "-DLIBUV_ROOT=$LIBUV_ROOT";
}
if ($LIBEV_ROOT) {
push @CM_OPTIONS, "-DLIBEV_ROOT=$LIBEV_ROOT";
}
if ($MAINTAINER_MODE) {
push @CM_OPTIONS, "-DLCB_MAINTAINER_MODE=1";
}
if ($OSX_UNIVERSAL_BUILD) {
push @CM_OPTIONS, "-DLCB_UNIVERSAL_BINARY=1";
}
if ($CMAKE_VERBOSE) {
push @CM_OPTIONS, "--debug-output";
}
if ($STATIC_LIBS) {
push @CM_OPTIONS, "-DBUILD_SHARED_LIBS=OFF", "-DLCB_BUILD_STATIC=1";
}
if ($CC) {
push @CM_OPTIONS, "-DCMAKE_C_COMPILER=$CC";
}
if ($CXX) {
push @CM_OPTIONS, "-DCMAKE_CXX_COMPILER=$CXX";
}
if ($USE_NINJA) {
push @CM_OPTIONS, "-DCMAKE_MAKE_PROGRAM=$USE_NINJA";
push @CM_OPTIONS, "-GNinja";
} else {
push @CM_OPTIONS, "-GUnix Makefiles";
}
if ($NO_SSL) {
push @CM_OPTIONS, "-DLCB_NO_SSL=$NO_SSL";
}
if ($OPENSSL_ROOT) {
push @CM_OPTIONS, "-DOPENSSL_ROOT_DIR=$OPENSSL_ROOT";
}
if ($SNAPPY_ROOT) {
push @CM_OPTIONS, "-DSNAPPY_ROOT=$SNAPPY_ROOT";
}
if ($NO_SNAPPY) {
push @CM_OPTIONS, "-DLCB_NO_SNAPPY=1";
}
if ($ENABLE_SNAPPY) {
push @CM_OPTIONS, "-DLCB_NO_SNAPPY=0";
}
if ($STATIC_SNAPPY) {
push @CM_OPTIONS, "-DLCB_STATIC_SNAPPY";
}
if ($LCB_USE_ASAN) {
push @CM_OPTIONS, "-DLCB_USE_ASAN=1";
}
if ($LCB_USE_COVERAGE) {
push @CM_OPTIONS, "-DLCB_USE_COVERAGE=1";
}
if ($NO_MOCK) {
push @CM_OPTIONS, "-DLCB_NO_MOCK=1";
}
if ($EMBED_LIBEVENT_PLUGIN) {
push @CM_OPTIONS, "-DLCB_EMBED_PLUGIN_LIBEVENT=1";
}
if ($BUILD_EXAMPLES) {
push @CM_OPTIONS, "-DLCB_BUILD_EXAMPLES=1";
}
if ($CMAKE_HOST) {
my $fname = "TOOLCHAIN-$CMAKE_HOST.cmake";
open my $fp, ">", $fname;
print $fp <<EOF;
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_C_COMPILER $CMAKE_HOST-gcc)
SET(CMAKE_CXX_COMPILER $CMAKE_HOST-g++)
SET(CMAKE_RC_COMPILER $CMAKE_HOST-windres)
SET(CMAKE_FIND_ROOT_PATH /usr/$CMAKE_HOST)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
EOF
$fname = realpath($fname);
push @CM_OPTIONS, "-DCMAKE_TOOLCHAIN_FILE=$fname";
}
print "$CMAKE_EXE ../ \\ \n";
foreach my $opt (@CM_OPTIONS) {
printf(" \"%s\" \\ \n", $opt);
}
unshift @CM_OPTIONS, "$CMAKE_EXE", $srcdir;
my $rv = system(@CM_OPTIONS);
if ($rv != 0) {
die("Couldn't invoke cmake");
}
if ($origdir eq $srcdir) {
chdir($origdir);
open(my $fh, ">", "Makefile");
print $fh <<EOF;
all:
\%::
\t\$(MAKE) -C $BUILD_DIR \$\@
include $BUILD_DIR/defs.mk
include packaging/rpm/package.mk
include packaging/deb/package.mk
EOF
close($fh);
}