1c94b4ab5SMark Nunberg#!/usr/bin/env perl
2
3# This script will eventually become the top-level configure directory ONCE
4# we've completely migrated away from autotools
5
6use strict;
7use warnings;
8use Getopt::Long;
9use File::Path;
10use File::Basename qw(dirname);
11use Cwd qw(getcwd realpath);
12use FindBin qw($Bin $RealBin);
13
14# Format here is:
15# [ Argument Name,
16#   Option format string,
17#   Option description,
18#   Default format string,
19#   Default value (ref)
20# ]
21
22my @HELP_DESCRIPTIONS = (
23    [ "enable-debug", "",
24        "Create a debug build",
25        "%d", \(my $DEBUG = 0) ],
26
27    [ "enable-profiler", "",
28        "Build with profiler support (gperftools)",
29        "%d", \(my $USE_PROFILER = 0) ],
30
31    [ "with-ninja", "s",
32        "Generate Ninja Makefiles",
33        "%s", \(my $USE_NINJA = "") ],
34
35    [ "prefix", "s",
36        "installation prefix",
37        "%s", \(my $PREFIX = "/usr/local") ],
38
39    [ "disable-tools", "",
40        "Don't build tools",
41        "%d", \(my $NO_TOOLS = 0)],
42
43    [ "disable-tests", "",
44        "Don't build tests",
45        "%d", \(my $NO_TESTS = 0)],
46
47    [ "with-libuv", "s",
48        "Path to LIBUV installation",
49        "%s", \(my $LIBUV_ROOT = "")],
50
51    [ "with-libev", "s",
52        "Path to LIBEV installation",
53        "%s", \(my $LIBEV_ROOT = "")],
54
55    [ "with-libevent", "s",
56        "Path to LIBEVENT installation",
57        "%s", \(my $LIBEVENT_ROOT = "")],
58
59    [ "with-cmake", "s",
60        "Executable to use as cmake",
61        "%s", \(my $CMAKE_EXE = "cmake")],
62
63    [ "with-openssl", "s",
64        "Path to OpenSSL installation",
65        "%s", \(my $OPENSSL_ROOT = "")],
66
67    [ "disable-plugins", "",
68        "Disable building of external plugins",
69        "%d", \(my $NO_PLUGINS = 0)],
70
71    [ "disable-cxx", "",
72        "Disable C++ targets",
73        "%d", \(my $NO_CXX = 0) ],
74    [ "disable-couchbasemock", "",
75        "Don't run tests with Mock",
76        "%d", \(my $NO_MOCK = 0) ],
77    [ "enable-maintainer-mode", "",
78        "Maintainer mode. Everything is strict",
79        "%d", \(my $MAINTAINER_MODE = 0)],
80
81    [ "enable-fat-binary", "",
82        "Build universal binaries on OS X",
83        "%d", \(my $OSX_UNIVERSAL_BUILD = 0)],
84
85    [ "cmake-verbose", "",
86        "Verbose CMake output",
87        "%d", \(my $CMAKE_VERBOSE = 0)],
88
89    [ "host", "s",
90        "Set host target for Win32 cross compilation",
91        "%s", \(my $CMAKE_HOST = "")],
92
93    [ "enable-static", "",
94        "Build static libraries",
95        "%d", \(my $STATIC_LIBS = 0)],
96    [ "enable-embedded-libevent-plugin", "",
97        "Embed the libevent plugin into the library's core",
98        "%d", \(my $EMBED_LIBEVENT_PLUGIN = 0) ],
99    [ "cc", "s",
100        "C Compiler",
101        "%s", \(my $CC = "") ],
102
103    [ "cxx", "s",
104        "C++ Compiler",
105        "%s", \(my $CXX = "") ],
106    [ "disable-ssl", "",
107        "Do not build SSL support",
108        "%d", \(my $NO_SSL = 0)],
109    [ "enable-asan", "",
110        "Enable LLVM AddressSanitizer support",
111        "%d", \(my $LCB_USE_ASAN = 0)],
112    [ "enable-coverage", "",
113        "Compile with code coverage instrumentation",
114        "%d", \(my $LCB_USE_COVERAGE = 0)],
115    [ "enable-examples", "",
116        "Build examples",
117        "%s", \(my $BUILD_EXAMPLES = 0)],
118    [ "build-dir", "s",
119        "Directory to build in",
120        "%s", \(my $BUILD_DIR = "build") ],
121    [ "skip-git-version", "",
122        "Skip version detection using git",
123        "%d", \(my $SKIP_GIT_VERSION = 0) ],
124
125    [ "help", "",
126        "This message", "%s", \(my $WANT_HELP = 0) ]
127);
128
129my @HELPLINES = ();
130my %GETOPT_ARGS = ();
131
132foreach my $optdesc (@HELP_DESCRIPTIONS) {
133    my ($name, $vfmt, $desc, $deflfmt, $vref) = @$optdesc;
134    my $go_key = $name;
135    if ($vfmt) {
136        $go_key .= "=$vfmt";
137    }
138    $GETOPT_ARGS{$go_key} = $vref;
139}
140
141GetOptions(%GETOPT_ARGS);
142
143if ($WANT_HELP) {
144    printf("configure.pl ... options\n");
145    foreach my $optdesc (@HELP_DESCRIPTIONS) {
146        my ($name, $vfmt, $desc, $fmt, $deflref) = @$optdesc;
147        printf("  --%-20s", $name);
148        if (length($name) > 18) {
149            printf("\n");
150            printf("%-20s%s\n","", $desc);
151        } else {
152            printf("%s.", $desc);
153        }
154        printf(" Default=".$fmt."\n", ${$deflref});
155    }
156
157    exit(0);
158}
159
160my $origdir = getcwd();
161my $srcdir = realpath("$RealBin/..");
162
163if ($origdir eq $srcdir) {
164    printf("Detected in-source build. Making '$BUILD_DIR' directory\n");
165    mkpath($BUILD_DIR);
166    chdir($BUILD_DIR);
167}
168
169if ($NO_CXX) {
170    $NO_TESTS=1;
171    $NO_TOOLS=1;
172}
173
174my @CM_OPTIONS = ();
175
176my @VARNAMES = (qw(CC CXX CFLAGS CPPFLAGS CXXFLAGS LDFLAGS LIBS));
177my %ENVOPTIONS = ();
178foreach my $var (@VARNAMES) {
179    $ENVOPTIONS{$var} = $ENV{$var};
180}
181
182foreach my $arg (@ARGV) {
183    my ($k,$v) = $arg =~ m/([^=]+)=(.*)/;
184    unless ($k && $v && exists $ENVOPTIONS{$k}) {
185        die("Invalid variable $arg");
186    }
187    $ENVOPTIONS{$k} = $v;
188}
189
190my $flags_common = "";
191my $flags_cxx = "";
192my $flags_cc = "";
193
194if ($ENVOPTIONS{CC}) { $CC = $ENVOPTIONS{CC}; }
195if ($ENVOPTIONS{CXX}) { $CXX = $ENVOPTIONS{CXX}; }
196if ($ENVOPTIONS{CPPFLAGS}) {
197    $flags_common = $ENVOPTIONS{CPPFLAGS};
198}
199$flags_cxx = $flags_common;
200$flags_cc = $flags_common;
201if ($ENVOPTIONS{CFLAGS}) {
202    $flags_cc .= " " . $ENVOPTIONS{CFLAGS};
203}
204if ($ENVOPTIONS{CXXFLAGS}) {
205    $flags_cxx .= " ".$ENVOPTIONS{CXXFLAGS};
206}
207if ($flags_cc) {
208    push @CM_OPTIONS, "-DCMAKE_C_FLAGS=$flags_cc";
209}
210if ($flags_cxx) {
211    push @CM_OPTIONS, "-DCMAKE_CXX_FLAGS=$flags_cxx";
212}
213if ($ENVOPTIONS{LDFLAGS}) {
214    # Flags for the linker
215    my $flags = $ENVOPTIONS{LDFLAGS};
216    foreach my $var (qw(EXE_LINKER_FLAGS SHARED_LINKER_FLAGS)) {
217        push @CM_OPTIONS, "-DCMAKE_${var}=$flags";
218    }
219}
220if ($ENVOPTIONS{LIBS}) {
221    warn("Don't know how to convert autotools 'LIBS' into CMake");
222}
223
224if ($DEBUG) {
225    push @CM_OPTIONS, "-DCMAKE_BUILD_TYPE=DEBUG";
226} else {
227    push @CM_OPTIONS, "-DCMAKE_BUILD_TYPE=RelWithDebInfo"
228}
229
230if ($USE_PROFILER) {
231    push @CM_OPTIONS, "-DLCB_USE_PROFILER=1";
232}
233
234if ($PREFIX) {
235    push @CM_OPTIONS, "-DCMAKE_INSTALL_PREFIX=$PREFIX";
236}
237if ($NO_TESTS) {
238    push @CM_OPTIONS, "-DLCB_NO_TESTS=1";
239}
240if ($NO_TOOLS) {
241    push @CM_OPTIONS, "-DLCB_NO_TOOLS=1";
242}
243
244if ($SKIP_GIT_VERSION) {
245    push @CM_OPTIONS, "-DLCB_SKIP_GIT_VERSION=1"
246}
247
248if ($NO_PLUGINS) {
249    push @CM_OPTIONS, "-DLCB_NO_PLUGINS=1";
250}
251if ($LIBUV_ROOT) {
252    push @CM_OPTIONS, "-DLIBUV_ROOT=$LIBUV_ROOT";
253}
254if ($LIBEV_ROOT) {
255    push @CM_OPTIONS, "-DLIBEV_ROOT=$LIBEV_ROOT";
256}
257if ($MAINTAINER_MODE) {
258    push @CM_OPTIONS, "-DLCB_MAINTAINER_MODE=1";
259}
260if ($OSX_UNIVERSAL_BUILD) {
261    push @CM_OPTIONS, "-DLCB_UNIVERSAL_BINARY=1";
262}
263if ($CMAKE_VERBOSE) {
264    push @CM_OPTIONS, "--debug-output";
265}
266if ($STATIC_LIBS) {
267    push @CM_OPTIONS, "-DBUILD_SHARED_LIBS=OFF", "-DLCB_BUILD_STATIC=1";
268}
269if ($CC) {
270    push @CM_OPTIONS, "-DCMAKE_C_COMPILER=$CC";
271}
272if ($CXX) {
273    push @CM_OPTIONS, "-DCMAKE_CXX_COMPILER=$CXX";
274}
275if ($USE_NINJA) {
276    push @CM_OPTIONS, "-DCMAKE_MAKE_PROGRAM=$USE_NINJA";
277    push @CM_OPTIONS, "-GNinja";
278} else {
279    push @CM_OPTIONS, "-GUnix Makefiles";
280}
281if ($NO_SSL) {
282    push @CM_OPTIONS, "-DLCB_NO_SSL=$NO_SSL";
283}
284if ($OPENSSL_ROOT) {
285    push @CM_OPTIONS, "-DOPENSSL_ROOT_DIR=$OPENSSL_ROOT";
286}
287if ($LCB_USE_ASAN) {
288    push @CM_OPTIONS, "-DLCB_USE_ASAN=1";
289}
290if ($LCB_USE_COVERAGE) {
291    push @CM_OPTIONS, "-DLCB_USE_COVERAGE=1";
292}
293if ($NO_MOCK) {
294    push @CM_OPTIONS, "-DLCB_NO_MOCK=1";
295}
296if ($EMBED_LIBEVENT_PLUGIN) {
297    push @CM_OPTIONS, "-DLCB_EMBED_PLUGIN_LIBEVENT=1";
298}
299if ($BUILD_EXAMPLES) {
300    push @CM_OPTIONS, "-DLCB_BUILD_EXAMPLES=1";
301}
302
303if ($CMAKE_HOST) {
304    # Write the toolchain file
305    my $fname = "TOOLCHAIN-$CMAKE_HOST.cmake";
306    open my $fp, ">", $fname;
307    print $fp <<EOF;
308SET(CMAKE_SYSTEM_NAME Windows)
309SET(CMAKE_C_COMPILER $CMAKE_HOST-gcc)
310SET(CMAKE_CXX_COMPILER $CMAKE_HOST-g++)
311SET(CMAKE_RC_COMPILER $CMAKE_HOST-windres)
312SET(CMAKE_FIND_ROOT_PATH /usr/$CMAKE_HOST)
313SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
314SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
315SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
316EOF
317    $fname = realpath($fname);
318    push @CM_OPTIONS, "-DCMAKE_TOOLCHAIN_FILE=$fname";
319}
320
321print "$CMAKE_EXE ../ \\ \n";
322foreach my $opt (@CM_OPTIONS) {
323    printf("    \"%s\" \\ \n", $opt);
324}
325
326unshift @CM_OPTIONS, "$CMAKE_EXE", $srcdir;
327my $rv = system(@CM_OPTIONS);
328if ($rv != 0) {
329    die("Couldn't invoke cmake");
330}
331
332if ($origdir eq $srcdir) {
333    chdir($origdir);
334    open(my $fh, ">", "Makefile");
335    print $fh <<EOF;
336all:
337
338\%::
339\t\$(MAKE) -C $BUILD_DIR \$\@
340
341include $BUILD_DIR/defs.mk
342include packaging/rpm/package.mk
343include packaging/deb/package.mk
344
345EOF
346    close($fh);
347}
348