summaryrefslogtreecommitdiff
path: root/infrastructure/makebuildenv.pl.in
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2018-02-20 21:49:13 -0500
committerReinhard Tartler <siretart@tauware.de>2018-02-20 21:49:13 -0500
commitf28f88e5e72ba1499409047a9d6985eb312c0232 (patch)
treec9c267f18264b3dfe715a363935bb6ac20904492 /infrastructure/makebuildenv.pl.in
parente19a5db232e1ef90e9a02159d2fbd9707ffe4373 (diff)
parent6d7e9562e8485591a4888f1fc2d3c6c657dc7a01 (diff)
Merge tag 'BoxBackup-0.12.master.180102.6d7e956' into upstream
Diffstat (limited to 'infrastructure/makebuildenv.pl.in')
-rwxr-xr-xinfrastructure/makebuildenv.pl.in1063
1 files changed, 726 insertions, 337 deletions
diff --git a/infrastructure/makebuildenv.pl.in b/infrastructure/makebuildenv.pl.in
index 005f2d25..d5ac9f2f 100755
--- a/infrastructure/makebuildenv.pl.in
+++ b/infrastructure/makebuildenv.pl.in
@@ -14,21 +14,21 @@ $|=1;
print "Box build environment setup.\n";
-my @implicit_deps = ('lib/common');
+# Modules that everything else depends on, without being explicitly specified.
+# Deprecated because we can't specify dependencies between them in the usual way,
+# and it's totally unnecessary anyway:
+my @implicit_deps;
# work out platform variables
use lib 'infrastructure';
use BoxPlatform;
-print "Building on '$build_os'.\n\n";
+print "Building on '$build_os $build_os_ver' using ".
+ ($bsd_make ? "BSD" : "GNU")." $make_command.\n\n";
# keep copy of command line args
my $makebuildenv_args = join(' ',@ARGV);
-# do command line arguments
-my $compile_line_extra = $platform_compile_line_extra;
-my $link_line_extra = $platform_link_line_extra;
-
# make sure local files directory exists
unless(-d 'local')
{
@@ -39,9 +39,6 @@ unless(-d 'local')
# flags about the environment
my %env_flags;
-$module_dependency{"lib/common"} = ["lib/win32"];
-push @implicit_deps, "lib/win32";
-
# print "Flag: $_\n" for(keys %env_flags);
# seed autogen code
@@ -211,7 +208,7 @@ for(@modules_files)
if(m/\AOMIT:(.+)/)
{
- if($1 eq $build_os or $1 eq $target_os)
+ if($1 eq $build_os or $1 eq $ac_target_os)
{
$modules_omitted = 1;
$modules_omitting = 1;
@@ -376,17 +373,159 @@ for my $mod (@modules, @implicit_deps)
closedir DIR;
}
-# Then write a makefile for each module
+my $default_cflags = '@CFLAGS@';
+my $default_cxxflags = '@CXXFLAGS@';
+$default_cflags =~ s/ -O2//g;
+$default_cxxflags =~ s/ -O2//g;
+my $debug_base_dir = 'debug';
+my $release_base_dir = 'release';
+my $debugger = '@with_debugger@';
+
+my $release_flags = "-O2";
+if ($target_windows)
+{
+ $release_flags = "-O0 -g";
+}
+
+# Then write a master Makefile, and a mini-Makefile for each module
print "done\n\nGenerating Makefiles...\n";
-my %module_resources_win32;
+my $makefile_ifdef_prefix = $bsd_make ? "." : "";
+my $autoconf_cppflags = '@CPPFLAGS@';
+my $autoconf_cxxflags = '@CXXFLAGS_STRICT@';
+my $autoconf_ldflags = '@LDFLAGS@';
+
+open MASTER_MAKEFILE, ">Makefile" or die "Makefile: $!";
+print MASTER_MAKEFILE <<__E;
+#
+# AUTOMATICALLY GENERATED FILE
+# do not edit!
+#
+#
+
+# "parcels" is defined near the end of this Makefile.
+default: parcels
+
+CC = @CC@
+CXX = @CXX@
+AR = @AR@
+RANLIB = @RANLIB@
+PERL = @PERL@
+WINDRES = @WINDRES@
+
+# Work around a mistake in QDBM (using <angled> includes for a file not in the
+# system path) by adding it to the include path with -I.
+DEFAULT_CFLAGS = $autoconf_cppflags $default_cflags $autoconf_cxxflags \\
+ $extra_platform_defines $platform_compile_line_extra \\
+ -DBOX_VERSION="\\"$product_version\\"" -Iqdbm
+DEFAULT_CXXFLAGS = $autoconf_cppflags $default_cxxflags $autoconf_cxxflags \\
+ $extra_platform_defines $platform_compile_line_extra \\
+ -DBOX_VERSION="\\"$product_version\\""
+LDFLAGS += $autoconf_ldflags \@LDADD_RDYNAMIC@ $platform_link_line_extra
+
+RELEASE_CFLAGS = \$(DEFAULT_CFLAGS) -DBOX_RELEASE_BUILD $release_flags
+RELEASE_CXXFLAGS = \$(DEFAULT_CXXFLAGS) -DBOX_RELEASE_BUILD $release_flags
+RELEASE_OUTBASE = $release_base_dir
+# http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode_using.html#debug_mode.using.mode
+DEBUG_CFLAGS = \$(DEFAULT_CFLAGS) -g -O0 -D_GLIBCXX_DEBUG
+DEBUG_CXXFLAGS = \$(DEFAULT_CXXFLAGS) -g -O0 -D_GLIBCXX_DEBUG
+DEBUG_OUTBASE = $debug_base_dir
+
+__E
+
+if ($bsd_make)
+{
+ print MASTER_MAKEFILE <<__E;
+.ifdef V
+HIDE =
+_CC = \$(CC)
+_CXX = \$(CXX)
+_LINK = \$(CXX)
+_WINDRES = \$(WINDRES)
+_AR = \$(AR)
+_RANLIB = \$(RANLIB)
+_PERL = \$(PERL)
+.else
+HIDE = @
+_CC = @ echo " [CC] " \$(*F) && \$(CC)
+_CXX = @ echo " [CXX] " \$(*F) && \$(CXX)
+_LINK = @ echo " [LINK] " \$(*F) && \$(CXX)
+_WINDRES = @ echo " [WINDRES]" \$(*F) && \$(WINDRES)
+_AR = @ echo " [AR] " \$(*F) && \$(AR)
+_RANLIB = @ echo " [RANLIB] " \$(*F) && \$(RANLIB)
+_PERL = @ echo " [PERL] " \$(*F) && \$(PERL) >/dev/null
+.endif
+
+__E
+}
+else
+{
+ print MASTER_MAKEFILE <<__E;
+HIDE = \$(if \$(V),,@)
+_CC = \$(if \$(V),\$(CC), @ echo " [CC] \$<" && \$(CC))
+_CXX = \$(if \$(V),\$(CXX), @ echo " [CXX] \$<" && \$(CXX))
+_LINK = \$(if \$(V),\$(CXX), @ echo " [LINK] \$@" && \$(CXX))
+_WINDRES = \$(if \$(V),\$(WINDRES), @ echo " [WINDRES] \$<" && \$(WINDRES))
+_AR = \$(if \$(V),\$(AR), @ echo " [AR] \$@" && \$(AR))
+_RANLIB = \$(if \$(V),\$(RANLIB), @ echo " [RANLIB] \$@" && \$(RANLIB))
+_PERL = \$(if \$(V),\$(PERL), @ echo " [PERL] \$@" && \$(PERL) >/dev/null)
+__E
+}
+
+my %module_resources_win32;
+my @debug_build_targets;
+my @release_build_targets;
+my @all_clean_targets;
+my @all_realclean_targets;
+my %mod_type_name;
+my %mod_end_targets;
+my %library_targets;
+
+# First, loop over all modules and quickly categorise them and generate the target filenames.
+# We need this to write correct dependency info into the makefile when modules are listed
+# out of order in modules.txt, which isn't strictly necessary but may look tidier.
for my $mod (@implicit_deps, @modules)
{
print $mod,"\n";
my ($type,$name) = split /\//,$mod;
-
+ if (not $name)
+ {
+ # External modules such as qdbm have no "type" in the directory path.
+ $name = $mod;
+ $type = 'lib';
+ }
+
+ # is target a library?
+ my $target_is_library = ($type ne 'bin' && $type ne 'test');
+
+ # make target name
+ my $end_target_file = $name;
+
+ if ($target_is_library)
+ {
+ $end_target_file .= '.a';
+ }
+ else
+ {
+ $end_target_file .= $platform_exe_ext;
+ }
+
+ $end_target_file = '_test'.$platform_exe_ext if $type eq 'test';
+
+ $mod_type_name{$mod} = [$type, $name];
+ $mod_end_targets{$mod} = $end_target_file;
+ $library_targets{$mod} = $target_is_library;
+}
+
+# Now loop over them again, generating makefile instructions etc.
+for my $mod (@implicit_deps, @modules)
+{
+ my ($type,$name) = @{$mod_type_name{$mod}};
+ my $end_target_file = $mod_end_targets{$mod};
+ my $target_is_library = $library_targets{$mod};
+
# add additional files for tests
if($type eq 'test')
{
@@ -464,7 +603,7 @@ __E
close FL;
}
- print TESTFILE "$runcmd\n";
+ print TESTFILE "$runcmd\nexit_status=\$?\n";
if (-d "$module/testfiles")
{
@@ -473,14 +612,24 @@ kill_daemons
__E
}
+ print TESTFILE "exit \$exit_status\n";
close TESTFILE;
}
- writetestfile("$mod/_t", "GLIBCXX_FORCE_NEW=1 ".
- './test' . $platform_exe_ext . ' "$@"', $mod);
- writetestfile("$mod/_t-gdb", "GLIBCXX_FORCE_NEW=1 ".
- 'gdb ./test' . $platform_exe_ext . ' "$@"', $mod);
-
+ writetestfile("$mod/t", "GLIBCXX_FORCE_NEW=1 ".
+ './_test' . $platform_exe_ext . ' "$@"', $mod);
+
+ if($debugger)
+ {
+ writetestfile("$mod/t-gdb", "GLIBCXX_FORCE_NEW=1 ".
+ $debugger . ' ./_test' . $platform_exe_ext . ' "$@"', $mod);
+ }
+ else
+ {
+ writetestfile("$mod/t-gdb",
+ "echo 'No debugger was detected by configure script'\n".
+ "exit 2");
+ }
}
my @all_deps_for_module;
@@ -514,123 +663,70 @@ __E
}
}
}
-
-
- # make include path
- my $include_paths = join(' ',map {'-I../../'.$_} @all_deps_for_module);
-
- # is target a library?
- my $target_is_library = ($type ne 'bin' && $type ne 'test');
- # make target name
- my $end_target = $name;
+ # get the list of library things to add -- in order of dependency
+ # so things link properly
+ my @lib_files;
+ my @dep_targets;
+ my @include_search_dirs;
- if ($target_is_library)
- {
- $end_target .= '.a';
- }
- else
+ foreach my $dep (reverse @all_deps_for_module)
{
- $end_target .= $platform_exe_ext;
+ my $dep_target = $mod_end_targets{$dep};
+ die "No output file found for $dep" unless $dep_target;
+ $dep_target = "$dep/$dep_target";
+ push @dep_targets, $dep_target;
+
+ if ($dep =~ m|^lib\/(.+)$|)
+ {
+ push @lib_files, $dep_target;
+ push @include_search_dirs, $dep;
+ }
+ elsif ($dep =~ m|^([^/]+)$|)
+ {
+ push @lib_files, $dep_target;
+ push @include_search_dirs, $dep;
+ }
}
- $end_target = 'test'.$platform_exe_ext if $type eq 'test';
+ # make include path
+ my $cpp_include_paths = join(' ',map {"-I$_"} @include_search_dirs);
+ print MASTER_MAKEFILE "${type}_${name}_includes = $cpp_include_paths\n";
# adjust for outdir
- $end_target = '$(OUTDIR)/' . $end_target;
+ my $debug_end_target = "\$(DEBUG_OUTBASE)/$mod/$end_target_file";
+ my $release_end_target = "\$(RELEASE_OUTBASE)/$mod/$end_target_file";
+ push @debug_build_targets, $debug_end_target;
+ push @release_build_targets, $release_end_target;
# start the makefile
- my $mk_name_extra = ($bsd_make)?'':'X';
- open MAKE,">$mod/Makefile".$mk_name_extra or die "Can't open Makefile for $mod\n";
- my $debug_link_extra = ($target_is_library)?'':'../../debug/lib/debug/debug.a';
-
- my $default_cxxflags = '@CXXFLAGS@';
- $default_cxxflags =~ s/ -O2//g;
-
- my $release_flags = "-O2";
- if ($target_windows)
- {
- $release_flags = "-O0 -g";
- }
-
- print MAKE <<__E;
+ open MINI_MODULE_MAKEFILE,">$mod/Makefile" or die "Can't open Makefile for $mod\n";
+ print MINI_MODULE_MAKEFILE <<__E;
#
# AUTOMATICALLY GENERATED FILE
# do not edit!
#
-#
-CXX = @CXX@
-AR = @AR@
-RANLIB = @RANLIB@
-PERL = @PERL@
-WINDRES = @WINDRES@
-
-DEFAULT_CXXFLAGS = @CPPFLAGS@ $default_cxxflags @CXXFLAGS_STRICT@ \\
- $include_paths $extra_platform_defines \\
- -DBOX_VERSION="\\"$product_version\\""
-LDFLAGS += @LDFLAGS@ @LDADD_RDYNAMIC@
-
-.ifdef RELEASE
-CXXFLAGS += -DBOX_RELEASE_BUILD $release_flags \$(DEFAULT_CXXFLAGS)
-OUTBASE = ../../release
-OUTDIR = ../../release/$mod
-DEPENDMAKEFLAGS = -D RELEASE
-VARIENT = RELEASE
-.else
-CXXFLAGS += -g \$(DEFAULT_CXXFLAGS)
-OUTBASE = ../../debug
-OUTDIR = ../../debug/$mod
-DEPENDMAKEFLAGS =
-VARIENT = DEBUG
-.endif
+${makefile_ifdef_prefix}ifdef RELEASE
+TARGET = $release_base_dir/$mod/$end_target_file
+${makefile_ifdef_prefix}else
+TARGET = $debug_base_dir/$mod/$end_target_file
+${makefile_ifdef_prefix}endif
-__E
+.PHONY: default
+default:
+ \$(MAKE) -C ../.. \$(TARGET)
- if ($bsd_make)
- {
- print MAKE <<__E;
-.ifdef V
-HIDE =
-_CXX = \$(CXX)
-_LINK = \$(CXX)
-_WINDRES = \$(WINDRES)
-_AR = \$(AR)
-_RANLIB = \$(RANLIB)
-_PERL = \$(PERL)
-.else
-HIDE = @
-_CXX = @ echo " [CXX] " \$(*F) && \$(CXX)
-_LINK = @ echo " [LINK] " \$(*F) && \$(CXX)
-_WINDRES = @ echo " [WINDRES]" \$(*F) && \$(WINDRES)
-_AR = @ echo " [AR] " \$(*F) && \$(AR)
-_RANLIB = @ echo " [RANLIB] " \$(*F) && \$(RANLIB)
-_PERL = @ echo " [PERL] " \$(*F) && \$(PERL) >/dev/null
-.endif
-
-__E
- }
- else
- {
- print MAKE <<__E;
-HIDE = \$(if \$(V),,@)
-_CXX = \$(if \$(V),\$(CXX), @ echo " [CXX] \$<" && \$(CXX))
-_LINK = \$(if \$(V),\$(CXX), @ echo " [LINK] \$@" && \$(CXX))
-_WINDRES = \$(if \$(V),\$(WINDRES), @ echo " [WINDRES] \$<" && \$(WINDRES))
-_AR = \$(if \$(V),\$(AR), @ echo " [AR] \$@" && \$(AR))
-_RANLIB = \$(if \$(V),\$(RANLIB), @ echo " [RANLIB] \$@" && \$(RANLIB))
-_PERL = \$(if \$(V),\$(PERL), @ echo " [PERL] \$@" && \$(PERL) >/dev/null)
+.PHONY: clean
+clean:
+ \$(MAKE) -C ../.. clean_${type}_${name}
+.PHONY: realclean
+realclean:
+ \$(MAKE) -C ../.. realclean_${type}_${name}
__E
- }
+ close MINI_MODULE_MAKEFILE;
- # if there is a Makefile.pre, include it now
- if(-e "$mod/Makefile.pre")
- {
- print MAKE ".include <Makefile.pre>\n\n";
- }
-
- # read directory
- opendir DIR,$mod;
+ opendir DIR, $mod;
my @items = readdir DIR;
closedir DIR;
@@ -643,10 +739,10 @@ __E
{
# Read items
my $d = "$mod/$di";
- opendir DIR,$d;
+ opendir DIR, $d;
my @i = readdir DIR;
closedir DIR;
- for(@i)
+ for (@i)
{
next if m/\A\./;
push @autogen_items,"$di/$_"
@@ -675,294 +771,587 @@ __E
}
}
- # ready for the rest of the details...
- my $make;
-
- # then... do the cpp files...
- my @obj_base;
- for my $file (@items)
+ # write the recipes for debug and release builds of each file
+ foreach my $var_prefix ('DEBUG', 'RELEASE')
{
- my $is_cpp = $file =~ m/\A(.+)\.cpp\Z/i;
- my $is_rc = $file =~ m/\A(.+)\.rc\Z/i;
- my $base = $1;
+ my $make;
- if ($target_windows)
- {
- next if not $is_cpp and not $is_rc;
- }
- else
+ # then... do the cpp files...
+ my @obj_base;
+ for my $file (@items)
{
- next if not $is_cpp;
- }
+ my $is_c = $file =~ m/\A(.+)\.c\Z/i;
+ my $is_cpp = $file =~ m/\A(.+)\.cpp\Z/i;
+ my $is_rc = $file =~ m/\A(.+)\.rc\Z/i;
+ my $base = $1;
- next if $file =~ /\A\._/; # Temp Mac OS Resource hack
+ # Don't try to compile .rc files except on Windows:
+ next if not $is_c and not $is_cpp and not ($is_rc and $target_windows);
+ next if $file =~ /\A\._/; # Temp Mac OS Resource hack
- # store for later
- push @obj_base,$base;
-
- # get the file...
- open FL,"$mod/$file";
- my $f;
- read FL,$f,-s "$mod/$file";
- close FL;
+ # store for later
+ push @obj_base, $base;
- my %dep;
+ # get the file...
+ open FL, "$mod/$file";
+ my $f;
+ read FL, $f, -s "$mod/$file";
+ close FL;
+
+ my %dep;
- while($f =~ m/\#include\s+"([^"]+?)"/g)
- {
- insert_dep($1, \%dep) if exists $hfiles{$1};
+ while($f =~ m/\#include\s+"([^"]+?)"/g)
+ {
+ insert_dep($1, \%dep) if exists $hfiles{$1};
+ }
+
+ # output filename
+ my $out_name = "\$(${var_prefix}_OUTBASE)/$mod/$base.o";
+
+ # write the line for this cpp file
+ my @dep_paths = map
+ {
+ ($hfiles{$_} eq $mod)
+ ? "$mod/$_"
+ : $hfiles{$_}."/$_"
+ }
+ keys %dep;
+
+ $make .= "$out_name: $mod/$file @dep_paths\n";
+
+ if ($is_c)
+ {
+ $make .= "\t\$(_CC) \$(${var_prefix}_CFLAGS) ".
+ "\$(${type}_${name}_includes) -DBOX_MODULE=\"\\\"$mod\\\"\" " .
+ "-c $mod/$file -o $out_name\n\n";
+ }
+ if ($is_cpp)
+ {
+ $make .= "\t\$(_CXX) \$(${var_prefix}_CXXFLAGS) ".
+ "\$(${type}_${name}_includes) -DBOX_MODULE=\"\\\"$mod\\\"\" " .
+ "-c $mod/$file -o $out_name\n\n";
+ }
+ elsif ($is_rc)
+ {
+ $make .= "\t\$(_WINDRES) $file $out_name\n\n";
+ my $res_list = $module_resources_win32{$mod};
+ $res_list ||= [];
+ push @$res_list, $base.'.o';
+ $module_resources_win32{$mod} = $res_list;
+ }
}
+
+ # need to see if the extra makefile fragments require extra object files
+ # or include any more makefiles
+ my @objs = @obj_base;
+ my @makefile_includes;
- # output filename
- my $out_name = '$(OUTDIR)/'.$base.'.o';
+ additional_objects_from_make_fragment("$mod/Makefile.extra", \@objs, \@makefile_includes);
+ additional_objects_from_make_fragment("$mod/Makefile.extra.$build_os", \@objs, \@makefile_includes);
+
+ my $prefixed_end_target = "\$(${var_prefix}_OUTBASE)/$mod/$end_target_file";
+ my $o_file_list = join(' ',map {"\$(${var_prefix}_OUTBASE)/$mod/$_.o"} sort @objs);
+ my @prefixed_lib_files = map {"\$(${var_prefix}_OUTBASE)/$_"} @lib_files;
+ my @prefixed_dep_targets = map {"\$(${var_prefix}_OUTBASE)/$_"} @dep_targets;
+
+ print MASTER_MAKEFILE "$prefixed_end_target: $o_file_list";
+ print MASTER_MAKEFILE " @prefixed_dep_targets" unless $target_is_library;
+ print MASTER_MAKEFILE "\n";
- # write the line for this cpp file
- my @dep_paths = map
- {
- ($hfiles{$_} eq $mod)
- ? $_
- : '../../'.$hfiles{$_}."/$_"
+ if ($target_windows)
+ {
+ foreach my $dep (@all_deps_for_module)
+ {
+ my $res_list = $module_resources_win32{$dep};
+ next unless $res_list;
+ $o_file_list .= ' '.join(' ',
+ map {"\$(${var_prefix}_OUTBASE)/$dep/$_"} @$res_list);
+ }
}
- keys %dep;
- $make .= $out_name.': '.join(' ',$file,@dep_paths)."\n";
-
- if ($is_cpp)
+ # stuff to make the final target...
+ if($target_is_library)
{
- $make .= "\t\$(_CXX) \$(CXXFLAGS) $compile_line_extra ".
- "-DBOX_MODULE=\"\\\"$mod\\\"\" " .
- "-c $file -o $out_name\n\n";
+ # make a library archive...
+ print MASTER_MAKEFILE "\t\$(HIDE) (rm -f $prefixed_end_target)\n";
+ print MASTER_MAKEFILE "\t\$(_AR) cq $prefixed_end_target $o_file_list\n";
+ print MASTER_MAKEFILE "\t\$(_RANLIB) $prefixed_end_target\n";
}
- elsif ($is_rc)
+ else
{
- $make .= "\t\$(_WINDRES) $file $out_name\n\n";
- my $res_list = $module_resources_win32{$mod};
- $res_list ||= [];
- push @$res_list, $base.'.o';
- $module_resources_win32{$mod} = $res_list;
+ # work out library options
+ # need to be... least used first, in absolute order they appear in the modules.txt file
+ my @libops;
+
+ sub libops_fill
+ {
+ my ($module, $libops_ref) = @_;
+
+ my $library_link_opts = $module_library_link_opts{$module};
+ if ($library_link_opts)
+ {
+ push @$libops_ref, @$library_link_opts;
+ }
+
+ my $deps = $module_dependency{$module};
+ foreach my $dep (@$deps)
+ {
+ libops_fill($dep, $libops_ref);
+ }
+ }
+
+ libops_fill($mod,\@libops);
+
+ my $lo = '';
+ my %ldone;
+ for(@libops)
+ {
+ next if exists $ldone{$_};
+ $lo .= ' '.$_;
+ $ldone{$_} = 1;
+ }
+
+ # link line...
+ print MASTER_MAKEFILE "\t\$(_LINK) \$(LDFLAGS) " .
+ "-o $prefixed_end_target $o_file_list " .
+ "@prefixed_lib_files $lo $platform_lib_files\n";
}
- }
-
- my $has_deps = ($#{$module_dependency{$mod}} >= 0);
-# ----- # always has dependencies with debug library
- $has_deps = 1;
- $has_deps = 0 if $target_is_library;
- # Dependency stuff
- my $deps_makeinfo;
- if($has_deps)
- {
- if($bsd_make)
+ # tests need to copy the test file over
+ if($type eq 'test')
{
- $deps_makeinfo = <<'__E';
-.BEGIN::
-.ifndef NODEPS
-. if $(.TARGETS) == ""
+ print MASTER_MAKEFILE <<__E;
+ \$(HIDE) cp $mod/t \$(${var_prefix}_OUTBASE)/$mod/t
+ \$(HIDE) chmod u+x \$(${var_prefix}_OUTBASE)/$mod/t
+ \$(HIDE) cp $mod/t-gdb \$(${var_prefix}_OUTBASE)/$mod/t-gdb
+ \$(HIDE) chmod u+x \$(${var_prefix}_OUTBASE)/$mod/t-gdb
__E
}
- else
+
+ print MASTER_MAKEFILE $make,"\n";
+
+ for(@makefile_includes)
{
- # gnu make
- $deps_makeinfo = <<'__E';
-.PHONY: dep_modules
-dep_modules:
-ifndef NODEPS
-ifeq ($(strip $(.TARGETS)),)
-__E
+ print MASTER_MAKEFILE "\n.include <$_>\n";
}
+}
+
+ print MASTER_MAKEFILE <<__E;
+clean_${type}_${name}:
+ rm -rf \$(DEBUG_OUTBASE)/$mod/*
+ rm -rf \$(RELEASE_OUTBASE)/$mod/*
+
+realclean_${type}_${name}: clean_${type}_${name}
+ rm -f $mod/t $mod/t-gdb $mod/Makefile
+ find $mod -name 'autogen_*' -type f -exec rm -f {} \\;
+__E
+ push @all_clean_targets, "clean_${type}_${name}";
+ push @all_realclean_targets, "realclean_${type}_${name}";
+
+ my $includes = "";
+
+ if(-e "$mod/Makefile.extra")
+ {
+ $includes .= ".include <$mod/Makefile.extra>\n\n";
+ }
+ if(-e "$mod/Makefile.extra.$build_os")
+ {
+ $includes .= ".include <$mod/Makefile.extra.$build_os>\n\n";
+ }
+
+ if(!$bsd_make)
+ {
+ # need to post process this into a GNU makefile
+ $includes =~ s/\A\.\s*(ifdef|else|endif|ifndef)/$1/;
+ $includes =~ s/\A\.\s*include\s+<(.+?)>/include $1/;
+ $includes =~ s/-D\s+(\w+)/$1=1/g;
+ }
+
+ print MASTER_MAKEFILE $includes;
+}
+
+my @parcels;
+my %parcel_contents;
+
+sub starts_with ($$)
+{
+ my ($string,$expected) = @_;
+ return substr($string, 0, length $expected) eq $expected;
+}
+
+sub os_matches ($)
+{
+ my ($prefix_string) = @_;
+ my @prefixes = split m'\,', $prefix_string;
+ foreach my $prefix (@prefixes)
+ {
+ return 1 if starts_with($build_os, $prefix);
+ return 1 if starts_with($ac_target_os, $prefix);
+ return 1 if starts_with("$ac_target_cpu-$ac_target_os",
+ $prefix);
+ return 1 if starts_with($ac_target, $prefix);
+ }
+ return 0;
+}
+
+my $copy_command = "cp -p";
+
+open PARCELS,"parcels.txt" or die "Can't open parcels file";
+{
+ my $cur_parcel = '';
+ while(<PARCELS>)
+ {
+ chomp; s/#.+\Z//; s/\s+\Z//; s/\s+/ /g;
+ next unless m/\S/;
- # run make for things we require
- for my $dep (@all_deps_for_module)
+ # omit bits on some platforms?
+ next if m/\AEND-OMIT/;
+ if(m/\AOMIT:(.+)/)
{
- my $dep_target = "";
- if ($dep =~ m|^lib/(.*)|)
+ if (os_matches($1))
{
- $dep_target = "\$(OUTBASE)/$dep/$1.a";
+ while(<PARCELS>)
+ {
+ last if m/\AEND-OMIT/;
+ }
}
- elsif ($dep =~ m|^.*/(.*)|)
+ next;
+ }
+
+ if (m'\AONLY:(.+)')
+ {
+ if (not os_matches($1))
{
- $dep_target = "\$(OUTBASE)/$dep/$1$platform_exe_ext";
+ while (<PARCELS>)
+ {
+ last if m'\AEND-ONLY';
+ }
}
- else
+ next;
+ }
+ next if (m'\AEND-ONLY');
+
+ if (m'\AEXCEPT:(.+)')
+ {
+ if (os_matches($1))
{
- $dep_target = "lib$dep.a";
+ while (<PARCELS>)
+ {
+ last if m'\AEND-EXCEPT';
+ }
}
-
- $deps_makeinfo .= <<EOF;
- \$(HIDE) ( \\
- cd ../../$dep; \\
- \$(MAKE) $sub_make_options -q \$(DEPENDMAKEFLAGS) -D NODEPS $dep_target \\
- || \$(MAKE) $sub_make_options \$(DEPENDMAKEFLAGS) -D NODEPS $dep_target \\
- )
-EOF
+ next;
}
-
- $deps_makeinfo .= ".\tendif\n.endif\n\n";
- }
- print MAKE $deps_makeinfo if $bsd_make;
-
- # get the list of library things to add -- in order of dependency
- # so things link properly
- my @lib_files;
- foreach my $dep (reverse @all_deps_for_module)
- {
- if ($dep =~ m|^lib\/(.+)$|)
+ next if (m'\AEND-EXCEPT');
+
+ # new parcel, or a new parcel definition?
+ if(m/\A\s+(.+)\Z/)
{
- push @lib_files, "\$(OUTBASE)/$dep/$1.a";
+ push @{$parcel_contents{$cur_parcel}},$1
}
- elsif ($dep =~ m|^([^/]+)$|)
+ else
{
- push @lib_files, "../../$dep/lib$1.a";
+ $cur_parcel = $_;
+ push @parcels,$_;
}
}
+}
+close PARCELS;
- # need to see if the extra makefile fragments require extra object files
- # or include any more makefiles
- my @objs = @obj_base;
- my @makefile_includes;
-
- additional_objects_from_make_fragment("$mod/Makefile.extra", \@objs, \@makefile_includes);
- additional_objects_from_make_fragment("$mod/Makefile.extra.$build_os", \@objs, \@makefile_includes);
+# create parcels directory
+mkdir "parcels",0755;
+mkdir "parcels/scripts",0755;
+
+print MASTER_MAKEFILE "parcels:\t",join(' ',map {"build-".$_} @parcels),"\n\n";
+
+my $runtest_script = $target_windows ? './infrastructure/mingw/runtest.sh'
+ : './runtest.pl';
+
+print MASTER_MAKEFILE <<__END_OF_FRAGMENT;
+.PHONY: test
+test: debug_tests release_tests
- my $o_file_list = join(' ',map {'$(OUTDIR)/'.$_.'.o'} sort @objs);
+.PHONY: debug_tests
+debug_tests:
+ $runtest_script ALL debug
- if ($has_deps and not $bsd_make)
+.PHONY: release_tests
+release_tests:
+ $runtest_script ALL release
+
+.PHONY: docs
+docs:
+ cd docs; \$(MAKE)
+
+__END_OF_FRAGMENT
+
+my $release_flag = BoxPlatform::make_flag('RELEASE');
+my @parcel_targets;
+
+for my $parcel (@parcels)
+{
+ my $version = BoxPlatform::parcel_root($parcel);
+ my $make_target = BoxPlatform::parcel_target($parcel);
+ my $dir = BoxPlatform::parcel_dir($parcel);
+ my @parcel_deps;
+
+ # Need to use BSD install on Solaris
+ my $install_bin = $build_os eq 'SunOS' ? '/usr/ucb/install' : 'install';
+
+ unless ($target_windows)
{
- print MAKE ".PHONY: all\n" .
- "all: dep_modules $end_target\n\n";
+ open SCRIPT,">parcels/scripts/install-$parcel" or die
+ "Can't open installer script for $parcel for writing";
+ print SCRIPT "#!/bin/sh\n\n";
}
- print MAKE $end_target,': ',$o_file_list;
- print MAKE " @lib_files" unless $target_is_library;
- print MAKE "\n";
-
- if ($target_windows)
+ for(@{$parcel_contents{$parcel}})
{
- foreach my $dep (@all_deps_for_module)
+ my @args = split /\s+/;
+
+ my ($type,$name,$dest) = @args;
+ my $optional = 0;
+ my $install = 1;
+
+ if ($type eq 'optional')
{
- my $res_list = $module_resources_win32{$dep};
- next unless $res_list;
- $o_file_list .= ' '.join(' ',
- map {'$(OUTBASE)/'.$dep."/$_"} @$res_list);
+ $optional = 1;
+ shift @args;
+ ($type,$name,$dest) = @args;
}
- }
- # stuff to make the final target...
- if($target_is_library)
- {
- # make a library archive...
- print MAKE "\t\$(HIDE) (echo -n > $end_target; rm $end_target)\n";
- print MAKE "\t\$(_AR) cq $end_target $o_file_list\n";
- print MAKE "\t\$(_RANLIB) $end_target\n";
- }
- else
- {
- # work out library options
- # need to be... least used first, in absolute order they appear in the modules.txt file
- my @libops;
-
- sub libops_fill
+ if ($type eq 'noinstall')
{
- my ($module, $libops_ref) = @_;
-
- my $library_link_opts = $module_library_link_opts{$module};
- if ($library_link_opts)
+ $install = 0;
+ shift @args;
+ ($type,$name,$dest) = @args;
+ }
+
+ if($type eq 'bin')
+ {
+ my $exeext = $platform_exe_ext;
+ print MASTER_MAKEFILE <<EOF;
+$dir/$name$exeext: release/bin/$name/$name$exeext
+ mkdir -p $dir
+ $copy_command release/bin/$name/$name$exeext $dir
+
+EOF
+ push @parcel_deps, "$dir/$name$exeext";
+ }
+ elsif ($type eq 'script')
+ {
+ # Replace any variables ($ac_target etc.) with their
+ # values.
+ $name =~ s|(\$[^/ ]+)|$1|eeg;
+ my $fullpath = $name;
+ my $filename = $name;
+ # remove path from script name
+ $filename =~ s{.*/}{};
+
+ print MASTER_MAKEFILE <<EOF;
+$dir/$filename: $fullpath
+ mkdir -p $dir
+EOF
+
+ if ($optional)
{
- push @$libops_ref, @$library_link_opts;
+ print MASTER_MAKEFILE "\ttest -r $fullpath " .
+ "&& $copy_command $fullpath $dir || true\n";
}
-
- my $deps = $module_dependency{$module};
- foreach my $dep (@$deps)
+ else
{
- libops_fill($dep, $libops_ref);
+ print MASTER_MAKEFILE "\t$copy_command $fullpath $dir\n";
}
+
+ print MASTER_MAKEFILE "\n";
+
+ push @parcel_deps, "$dir/$filename";
}
-
- libops_fill($mod,\@libops);
-
- my $lo = '';
- my %ldone;
- for(@libops)
+ elsif($type eq 'man')
{
- next if exists $ldone{$_};
- $lo .= ' '.$_;
- $ldone{$_} = 1;
+ print MASTER_MAKEFILE <<EOF;
+$dir/${name}.gz: docs/man/${name}.gz
+ mkdir -p $dir
+ $copy_command docs/man/${name}.gz $dir
+
+EOF
+ # Releases have the docs pre-made, but users
+ # may want to rebuild them for some reason.
+ my $docbook_source = "docs/docbook/${name}";
+ $docbook_source =~ s/\.[58]$/.xml/;
+ print MASTER_MAKEFILE <<EOF;
+docs/man/${name}.gz: $docbook_source docs/docbook/bb-man.xsl
+ cd docs; \$(MAKE) man/${name}.gz
+
+EOF
+ push @parcel_deps, "$dir/${name}.gz";
}
-
- # link line...
- print MAKE "\t\$(_LINK) \$(LDFLAGS) $link_line_extra " .
- "-o $end_target $o_file_list " .
- "@lib_files $lo $platform_lib_files\n";
- }
+ elsif($type eq 'html')
+ {
+ print MASTER_MAKEFILE <<EOF;
+$dir/docs/${name}.html: docs/htmlguide/man-html/${name}.html
+ mkdir -p $dir/docs
+ $copy_command docs/htmlguide/man-html/${name}.html $dir/docs
- # tests need to copy the test file over
- if($type eq 'test')
- {
- print MAKE "\tcp _t \$(OUTDIR)/t\n\tchmod u+x \$(OUTDIR)/t\n";
- print MAKE "\tcp _t-gdb \$(OUTDIR)/t-gdb\n\tchmod u+x \$(OUTDIR)/t-gdb\n";
+EOF
+ # Releases have the docs pre-made, but users
+ # may want to rebuild them for some reason.
+ my $docbook_source = "docs/docbook/${name}.xml";
+ print MASTER_MAKEFILE <<EOF;
+docs/htmlguide/man-html/${name}.html: $docbook_source docs/docbook/bb-nochunk-book.xsl
+ cd docs; \$(MAKE) htmlguide/man-html/${name}.html
+
+EOF
+ push @parcel_deps, "$dir/docs/${name}.html";
+ }
+ elsif ($type eq 'subdir')
+ {
+ push @parcel_deps, "build_${type}_${name}";
+ }
}
- # dependency line?
- print MAKE "\n";
+ print MASTER_MAKEFILE <<EOF;
+build-$parcel: $make_target
- # module dependencies for GNU make?
- print MAKE $deps_makeinfo if !$bsd_make;
-
- # print the rest of the file
- print MAKE $make,"\n";
-
- # and a clean target
- print MAKE <<EOF;
-clean:
- -rm -rf \$(OUTDIR)/*
-. ifndef SUBCLEAN
+$make_target: @parcel_deps
+ test -d $dir || mkdir $dir
EOF
- for my $dep (@all_deps_for_module)
- {
- print MAKE "\t\$(HIDE) (cd ../../$dep; \$(MAKE) \$(DEPENDMAKEFLAGS) -D SUBCLEAN clean)\n";
- }
- print MAKE ".\tendif\n";
+
+ push @parcel_targets, "build-$parcel";
- # include any extra stuff
- print MAKE "\n\n";
- if(-e "$mod/Makefile.extra")
- {
- print MAKE ".include <Makefile.extra>\n\n";
- }
- if(-e "$mod/Makefile.extra.$build_os")
+ for(@{$parcel_contents{$parcel}})
{
- print MAKE ".include <Makefile.extra.$build_os>\n\n";
+ my @args = split /\s+/;
+
+ my ($type,$name,$dest) = @args;
+
+ my $optional = 0;
+ my $install = 1;
+
+ if ($type eq 'optional')
+ {
+ $optional = 1;
+ shift @args;
+ ($type,$name,$dest) = @args;
+ }
+
+ if ($type eq 'noinstall')
+ {
+ $install = 0;
+ shift @args;
+ ($type,$name,$dest) = @args;
+ }
+
+ if ($type eq 'script')
+ {
+ # remove path from script name
+ $name =~ s{.*/}{};
+ }
+
+ if ($type eq 'html')
+ {
+ $dest = "share/doc/@PACKAGE_TARNAME@";
+ $name = "docs/$name.html";
+ }
+
+ if ($type eq 'man')
+ {
+ $name =~ /([0-9])$/;
+ $dest = "man/man$1";
+ $name =~ s/$/\.gz/;
+ }
+
+ if ($install and not $target_windows and not $type eq "subdir")
+ {
+ my $local_install_dir = $install_into_dir;
+ if (defined $dest)
+ {
+ if ($dest =~ m,^/,)
+ {
+ # Don't add $prefix if $dest is a literal path
+ $local_install_dir = $dest;
+ }
+ else
+ {
+ $local_install_dir = "@prefix@/$dest";
+ }
+ }
+ print SCRIPT "mkdir -p " .
+ "\${DESTDIR}$local_install_dir/\n";
+ print SCRIPT "$install_bin $name " .
+ "\${DESTDIR}$local_install_dir\n";
+ }
}
- for(@makefile_includes)
- {
- print MAKE ".include <$_>\n\n";
+
+ unless ($target_windows)
+ {
+ close SCRIPT;
+ chmod 0755,"parcels/scripts/install-$parcel";
}
- # and finally a target for rebuilding the build system
- print MAKE "\nbuildsystem:\n\t(cd ../..; perl ./infrastructure/makebuildenv.pl $makebuildenv_args)\n\n";
-
- close MAKE;
+ my $root = BoxPlatform::parcel_root($parcel);
- if(!$bsd_make)
+ unless ($target_windows)
{
- # need to post process this into a GNU makefile
- open MAKE,">$mod/Makefile";
- open MAKEB,"$mod/MakefileX";
+ print MASTER_MAKEFILE "\tcp parcels/scripts/install-$parcel $dir\n";
+ }
- while(<MAKEB>)
- {
- s/\A\.\s*(ifdef|else|endif|ifndef)/$1/;
- s/\A\.\s*include\s+<(.+?)>/include $1/;
- s/-D\s+(\w+)/$1=1/g;
- print MAKE;
- }
+ print MASTER_MAKEFILE "\t(cd parcels; tar cf - $root | gzip -9 - > $root.tgz )\n";
+
+ print MASTER_MAKEFILE "\n";
- close MAKEB;
- close MAKE;
- unlink "$mod/MakefileX";
+ unless ($target_windows)
+ {
+ print MASTER_MAKEFILE "install-$parcel:\n";
+ print MASTER_MAKEFILE "\t(cd $dir; ./install-$parcel)\n\n";
}
}
+print MASTER_MAKEFILE <<EOF;
+
+debug_build: @debug_build_targets
+release_build: @release_build_targets
+parcels: @parcel_targets
+
+# well-known targets that users might expect to be able to build:
+install:
+ cat local/install.msg
+
+clean: @all_clean_targets
+ cd docs; \$(MAKE) clean
+
+realclean: clean @all_realclean_targets
+ find release debug -type f -exec rm -f {} \\;
+
+# and finally a target for rebuilding the build system:
+buildsystem:
+ perl ./infrastructure/makebuildenv.pl $makebuildenv_args
+EOF
+
+for my $parcel (@parcels)
+{
+ # need to use -f to avoid error if they don't exist (already cleaned)
+ print MASTER_MAKEFILE "\trm -rf ", BoxPlatform::parcel_dir($parcel), "\n";
+ print MASTER_MAKEFILE "\trm -f ", BoxPlatform::parcel_target($parcel), "\n";
+}
+
+open INSTALLMSG,">local/install.msg" or die "Can't open install message file for writing";
+print INSTALLMSG <<__E;
+
+Parcels need to be installed separately, and as root. Type one of the following:
+
+__E
+
+for(@parcels)
+{
+ print INSTALLMSG " $make_command install-".$_."\n";
+}
+print INSTALLMSG "\n";
+
+close INSTALLMSG;
+
+close MASTER_MAKEFILE;
+
print "\nType 'cd <module_dir>; $make_command' to build a module\n\n";
if($modules_omitted)