From 7c01d8c6eb3c3756b3dbec4b5a8ff2c988f13145 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Thu, 15 May 2008 11:20:33 +0200 Subject: [PATCH] Added libucw build system from Sherlock v3.12.2. No changes have been made except for excluding genhash.c and its Makefile. --- build/Makebottom | 195 +++++++++++++++++++++++++++++++++++++++++++++++ build/Maketop | 82 ++++++++++++++++++++ build/genconf | 81 ++++++++++++++++++++ build/lib-deps | 22 ++++++ build/lib-flags | 24 ++++++ build/mergedeps | 21 +++++ build/tester | 139 +++++++++++++++++++++++++++++++++ 7 files changed, 564 insertions(+) create mode 100644 build/Makebottom create mode 100644 build/Maketop create mode 100755 build/genconf create mode 100755 build/lib-deps create mode 100755 build/lib-flags create mode 100755 build/mergedeps create mode 100755 build/tester diff --git a/build/Makebottom b/build/Makebottom new file mode 100644 index 0000000..b6f716e --- /dev/null +++ b/build/Makebottom @@ -0,0 +1,195 @@ +# Bottom part of Makefile for the UCW Libraries +# (c) 1997--2007 Martin Mares + +# The run tree + +runtree: run/.tree-stamp $(addsuffix /.dir-stamp,$(addprefix $(o)/,$(DIRS))) + +run/.tree-stamp: $(o)/config.mk + $(M)Creating runtree + $(Q)mkdir -p run $(addprefix run/, cf $(EXTRA_RUNDIRS) $(INSTALL_RUNDIRS)) + $(Q)touch run/.tree-stamp + +# Miscellaneous targets + +programs: $(PROGS) +datafiles: $(DATAFILES) +tests: $(TESTS) +configs: $(addprefix run/cf/,$(CONFIGS)) + +tags: + etags `find . -name "*.[ch]"` + +# Black magic with dependencies. It would be more correct to make "depend.new" +# a prerequisite for "depend", but "depend.new" often has the same timestamp +# as "depend" which would confuse make a lot and either force remaking anyway +# or (as in current versions of GNU make) erroneously skipping the remaking. + +-include $(o)/depend + +$(o)/depend: force + $(Q)if [ -s $(o)/depend.new ] ; then $(s)/build/mergedeps $(o)/depend $(o)/depend.new ; >$(o)/depend.new ; fi + +force: + +# Rules for directories + +%.dir-stamp: + $(Q)mkdir -p $(@D) && touch $@ + +# Rules for configuration files + +run/cf/%: custom/cf/% $(o)/config.mk $(s)/build/genconf + $(M)CF $< + $(Q)$(s)/build/genconf $< $@ $(o)/config.mk + +run/cf/%: $(s)/cf/% $(o)/config.mk $(s)/build/genconf + $(M)CF $< + $(Q)$(s)/build/genconf $< $@ $(o)/config.mk + +# Rules for libraries + +%.a: + $(M)AR $@ + $(Q)rm -f $@ + $(Q)ar rcs $@ $^ +ifdef CONFIG_INSTALL_API + $(Q)$(call symlink,$@,run/lib) +endif + +%.so: + $(M)LD $@ + $(Q)$(CC) $(LSHARED) $(LDFLAGS) -o $@ $^ + $(Q)$(call symlink,$@,run/lib) + +$(o)/%.pc: $(s)/%.pc $(o)/%.$(LS) + $(M)PC $< + $(Q)DEPS="$(shell $(s)/build/lib-deps $^)" LIBDIR=$(@D) $(s)/build/genconf $< $@ $(o)/config.mk + $(Q)mkdir -p $(o)/pkgconfig + $(Q)$(call symlink,$@,$(o)/pkgconfig) + +# Rules for public API + +ifdef CONFIG_INSTALL_API + +API_ROOT:=$(shell pwd)/run +INSTALL_RUNDIRS+=include lib/pkgconfig +api: $(API_INCLUDES) $(addprefix run/lib/pkgconfig/,$(addsuffix .pc,$(API_LIBS))) + +$(o)/%/.include-stamp: + $(Q)$(s)/build/install-includes $($@ "s@^libdir=.*@libdir=$(API_ROOT)/lib@;s@^incdir=.*@incdir=$(API_ROOT)/include@" + +else +api: +endif + +# Rules for compiling C + +$(o)/%.o: $(s)/%.c $(o)/autoconf.h + $(M)CC $< + $(Q)DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -c -o $@ $< + +$(o)/%.o: %.c $(o)/autoconf.h + $(M)CC $< + $(Q)DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -c -o $@ $< + +%.o: %.c $(o)/autoconf.h + $(M)CC $< + $(Q)DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -c -o $@ $< + +$(o)/%.oo: $(s)/%.c $(o)/autoconf.h + $(M)CC-SO $< + $(Q)DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) $(CSHARED) -c -o $@ $< + +$(o)/%.oo: %.c $(o)/autoconf.h + $(M)CC-SO $< + $(Q)DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) $(CSHARED) -c -o $@ $< + +%.oo: %.c $(o)/autoconf.h + $(M)CC-SO $< + $(Q)DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) $(CSHARED) -c -o $@ $< + +$(o)/%-tt.o: $(s)/%.c $(o)/autoconf.h + $(M)CC-TEST $< + $(Q)DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -DTEST -c -o $@ $< + +# Rules for testing + +$(o)/%-t: $(o)/%-tt.o $(TESTING_DEPS) + $(M)LD-TEST $@ + $(Q)$(CC) $(LDFLAGS) -o $@ $(shell $(s)/build/lib-flags $^) $(LIBS) + +$(o)/%.test: $(s)/%.t $(s)/build/tester + $(M)TEST $@ + $(Q)$(s)/build/tester --rundir=run $(TESTERFLAGS) $< && touch $@ + +# Rules for binaries + +BINDIR=bin + +$(o)/%: $(o)/%.o + $(M)LD $@ + $(Q)$(CC) $(LDFLAGS) -o $@ $(shell $(s)/build/lib-flags $^) $(LIBS) + $(Q)$(call symlink,$@,run/$(BINDIR)) + +$(o)/%: $(s)/%.sh $(o)/config.mk $(s)/build/genconf + $(M)PP $< + $(Q)$(s)/build/genconf $< $@ $(o)/config.mk + $(Q)chmod +x $@ + $(Q)$(call symlink,$@,run/$(BINDIR)) + +$(o)/%: %.sh $(o)/config.mk $(s)/build/genconf + $(M)PP $< + $(Q)$(s)/build/genconf $< $@ $(o)/config.mk + $(Q)chmod +x $@ + $(Q)$(call symlink,$@,run/$(BINDIR)) + +$(o)/%: $(s)/%.pl $(o)/config.mk $(s)/build/genconf + $(M)PP $< + $(Q)$(s)/build/genconf $< $@ $(o)/config.mk + $(Q)chmod +x $@ + $(Q)$(call symlink,$@,run/$(BINDIR)) + +$(o)/%: %.pl $(o)/config.mk $(s)/build/genconf + $(M)PP $< + $(Q)$(s)/build/genconf $< $@ $(o)/config.mk + $(Q)chmod +x $@ + $(Q)$(call symlink,$@,run/$(BINDIR)) + +PERL_MODULE_DIR=UCW + +$(o)/%.pm: $(s)/%.pm + $(M)"PM $< -> run/lib/perl5/$(PERL_MODULE_DIR)/$(@F)" + $(Q)cp $^ $@ + $(Q)$(call symlink,$@,run/lib/perl5/$(PERL_MODULE_DIR)) + +$(o)/%.pm: %.pm + $(M)"PM $< -> run/lib/perl/$(PERL_MODULE_DIR)/$(@F)" + $(Q)cp $^ $@ + $(Q)$(call symlink,$@,run/lib/perl5/$(PERL_MODULE_DIR)) + +# Rules for data files + +DATADIR=lib + +$(DATAFILES): $(o)/%: $(s)/% + $(M)DATA $< + $(Q)cp $^ $@ + $(Q)$(call symlink,$@,run/$(DATADIR)) + +# Default installation target + +default-install: + SH_EXTRA_RUNDIRS="$(sort $(EXTRA_RUNDIRS))" SH_INSTALL_RUNDIRS="$(sort $(INSTALL_RUNDIRS))" SH_CONFIGS="$(sort $(CONFIGS))" SH_AUTO_CONFIRM="$(CONFIRM)" $(s)/build/installer $(INSTALL_DIR) + +# Don't delete intermediate targets. There shouldn't be any, but due to bugs +# in GNU Make rules with targets in not-yet-existing directories are ignored +# when searching for implicit rules and thence targets considered intermediate. +.SECONDARY: + +.PHONY: all clean distclean runtree programs api datafiles force tags configs dust install default-install diff --git a/build/Maketop b/build/Maketop new file mode 100644 index 0000000..cf93e1b --- /dev/null +++ b/build/Maketop @@ -0,0 +1,82 @@ +# Top part of Makefile for the UCW Libraries +# (c) 1997--2007 Martin Mares + +# Set to 1 if you want verbose output +V=0 + +# Set to 'y' (or 'n') if you want to auto-confirm (auto-reject) all questions in build/installer +CONFIRM= + +# Disable all built-in rules and variables. Speeds up make and simplifies debugging. +MAKEFLAGS+=-rR + +CFLAGS=$(CLANG) $(COPT) $(CDEBUG) $(CWARNS) $(CEXTRA) -I. -I$(o) -I$(s) +LDFLAGS=$(LOPT) $(LEXTRA) + +DIRS= +PROGS= +CONFIGS= +TESTS= +EXTRA_RUNDIRS=tmp log +INSTALL_RUNDIRS=bin lib +API_INCLUDES= +API_LIBS= + +# Various files whose type does not fit into PROGS +DATAFILES= + +ifdef CONFIG_SHARED +LS=so +OS=oo +else +LS=a +OS=o +endif + +ifdef CONFIG_DARWIN +SOEXT=bundle +else +SOEXT=so +endif + +# Whenever "make -s" (silent) is run, turn on verbose mode (paradoxical, but gives the right result) +ifneq ($(findstring s,$(MAKEFLAGS)),) +V=1 +endif + +# Define M (message) and Q (quiet command prefix) macros and also MAKESILENT passed to sub-makes +ifeq ($(V),1) +M=@\# +Q= +MAKESILENT= +else +M=@echo # +Q=@ +MAKESILENT=-s +endif + +# Clean needs to be a double-colon rule since we want sub-makefiles to be able +# to define their own cleanup actions. +dust:: + rm -f `find . -path "*~" -or -name "\#*\#" -or -name core` + rm -f allocs.tmp cscope.out TAGS + +clean:: dust + rm -rf `find obj -mindepth 1 -maxdepth 1 -not \( -name config.mk -o -name autoconf.h \)` + rm -rf tests run/{bin,lib,include,.tree-stamp} + +distclean:: clean + rm -rf obj run + +testclean:: + rm -f `find obj -name "*.test"` + +# Extra default rules (appended to by submakefiles) +extras:: + +# Relative symlinks and other pathname manipulation macros +empty:= +space:=$(empty) $(empty) +backref=$(subst $(space),/,$(patsubst %,..,$(subst /,$(space),$(1)))) +tack-on=$(if $(patsubst /%,,$(2)),$(1)/$(2),$(2)) +symlink=ln -sf $(call tack-on,$(call backref,$(2)),$(1)) $(2)/ diff --git a/build/genconf b/build/genconf new file mode 100755 index 0000000..eaf2d1c --- /dev/null +++ b/build/genconf @@ -0,0 +1,81 @@ +#!/usr/bin/perl +# Configuration file and script preprocessor +# (c) 2004--2007 Martin Mares + +use strict; +use warnings; + +@ARGV == 3 or die "Usage: genconf "; + +open CF, $ARGV[2] or die "Unable to open $ARGV[2]"; +my %options = (); +my %vars = (); +sub opt { + my ($k,$v) = @_; + $vars{$k} = $v; + $options{$k} = 1 if ($k =~ /^CONFIG_/); +} +foreach my $k (keys %ENV) { + opt($k, $ENV{$k}); +} +while () { + chomp; + if (my ($k,$v) = /^(\w+)=(.*)/) { + $v =~ s/\s+$//; + opt($k, $v); + } +} +close CF; + +sub eval_expr { + $_ = shift @_; + s/\b(CONFIG_\w+)\b/defined($options{$1}) ? 1 : 0/ge; + return eval $_; +} + +open IN, $ARGV[0] or die "Unable to open $ARGV[0]"; +open OUT, ">$ARGV[1]" or die "Unable to create $ARGV[1]"; +my @ifs = (); # stack of conditions, 1=satisfied, -1=unsatisfied, 0=shadowed +my $empty = 0; # last line was empty +while () { + if (/^#ifdef\s+(\w+)/) { + push @ifs, (@ifs && $ifs[$#ifs] <= 0) ? 0 : (defined $options{$1}) ? 1 : -1; + } elsif (/^#ifndef\s+(\w+)/) { + push @ifs, (@ifs && $ifs[$#ifs] <= 0) ? 0 : (defined $options{$1}) ? -1 : 1; + } elsif (/^#if\s(.*)$/) { + push @ifs, (@ifs && $ifs[$#ifs] <= 0) ? 0 : (eval_expr $1) ? 1 : -1; + } elsif (/^#endif/) { + defined pop @ifs || die "Improper nesting of conditionals"; + } elsif (/^#else/) { + my $x = pop @ifs; + defined $x || die "Improper nesting of conditionals"; + push @ifs, $x >= 0 ? 0 : 1; + } elsif (/^#elsif\s(.*)$/) { + my $x = pop @ifs; + defined $x || die "Improper nesting of conditionals"; + push @ifs, $x >= 0 ? 0 : (eval_expr $1) ? 1 : -1; + } else { + @ifs && $ifs[$#ifs] <= 0 && next; + if (/^$/) { + $empty && next; + $empty = 1; + } else { $empty = 0; } + if (/^#pipe\s+(.+)/) { + my $cmd = $1; + my $val = `$cmd`; + die "Piped command '$cmd' failed" if $?; + print OUT `$1`; + } else { + sub repl ($) { + my $v = shift @_; + exists $vars{$v} or die "Cannot substitute $v: variable not set"; + return $vars{$v}; + } + s/@(\w+)@/repl($1)/ge; + print OUT; + } + } +} +@ifs && die "Unterminated #ifdef"; +close IN; +close OUT; diff --git a/build/lib-deps b/build/lib-deps new file mode 100755 index 0000000..1019bc2 --- /dev/null +++ b/build/lib-deps @@ -0,0 +1,22 @@ +#!/bin/bash +# +# A tool which builds a list of dependent libraries from the list +# of pkg-config files. +# +# (c) 2007 Martin Mares , placed under GNU LGPL +# + +set -e + +shift +SEEN= +while [ -n "$1" ] ; do + case "$1" in + *.pc) if [ -n "$SEEN" ] ; then echo -n ", " ; fi + echo -n "`basename $1 .pc`" + SEEN=1 + ;; + *) ;; + esac + shift +done diff --git a/build/lib-flags b/build/lib-flags new file mode 100755 index 0000000..97d8956 --- /dev/null +++ b/build/lib-flags @@ -0,0 +1,24 @@ +#!/bin/bash +# +# A preprocessor for linker arguments, which replaces references to .pc +# files by results of the proper calls to pkg-config. +# +# (c) 2007 Martin Mares , placed under GNU LGPL +# + +set -e + +PC= +while [ -n "$1" ] ; do + case "$1" in + *.pc) PC="$PC `basename $1 .pc`" + ;; + *) echo -n " $1" + ;; + esac + shift +done +if [ -n "$PC" ] ; then + echo -n " " + PKG_CONFIG_PATH="$PKG_CONFIG_PATH:obj/pkgconfig" pkg-config --libs $PC +fi diff --git a/build/mergedeps b/build/mergedeps new file mode 100755 index 0000000..e1c467d --- /dev/null +++ b/build/mergedeps @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +@ARGV == 2 or die "Usage: mergedeps "; +foreach $a (@ARGV) { + open F, "$a" or next; + $t = ""; + while () { + $t .= $_; + if (! /\\$/) { + ($t =~ /^(.*):/) || die "Parse error at $t"; + $rules{$1} = $t; + $t = ""; + } + } + close F; +} +open(F,">" . $ARGV[0]) || die "Unable to write output file"; +foreach $a (sort keys %rules) { + print F $rules{$a}; +} +close F; diff --git a/build/tester b/build/tester new file mode 100755 index 0000000..f66713e --- /dev/null +++ b/build/tester @@ -0,0 +1,139 @@ +#!/usr/bin/perl +# A simple unit testing script +# (c) 2004--2007 Martin Mares +# (c) 2007 Pavel Charvat + +# Tests in the test file have a syntax similar to mail headers, +# individual test case are separated by blank lines and they can contain +# the following fields: +# +# Name: name of the case (default: sequence number since start of file) +# Run: command to run (default: command from the previous test case) +# This can be an arbitrary shell pipeline, sequences $0 to $9 are +# replaced by file names of In or Out files (see below). +# In: lines to pass to the program as standard input +# Out: lines to expect at the program's standard output +# In: lines to pass to the program as input file +# Out: lines to expect from the program in output file +# Both In and Out can be specified simultaneously if we +# are testing a program which modifies some of its input files. +# Exit: expected exit code of the program (default: 0) + +use Getopt::Long; + +my $verbose = 0; +my $rundir = "."; +GetOptions("verbose!" => \$verbose, + "rundir=s" => \$rundir) + or die "Usage: tester [--verbose] [--rundir=] \n"; + +my @tests = (); +my $tt; +my $append_to; + +while (<>) { + /^#/ && next; + if (/^\s*$/) { + $tt = undef; + $append_to = undef; + } elsif (defined($append_to) && /^\s+(.*)$/) { + $$append_to .= "\n$1"; + } elsif (my ($n,$v) = /^(\w+):\s+(.*)$/) { + if (!$tt) { + $tt = {}; + push @tests, $tt; + } + ($tt->{$n}) && die "$n already defined"; + $tt->{$n} = $v; + $append_to = \($tt->{$n}); + } else { + die "Test script syntax error"; + } +} + +if (! -d "$rundir/tmp") { + mkdir "$rundir/tmp" or die "Unable to create $rundir/tmp: $!"; +} + +my $i = 0; +my $errors = 0; +my $prev_run = undef; +TEST: foreach $tt (@tests) { + $i++; + my $name = $tt->{'Name'} || $i; + print "Test $name: "; + $run = ($tt->{'Run'} || $prev_run) or die "Don't know what to run"; + $prev_run = $run; + + my @out_files = (); + my @out_checks = (); + my $redirs = ""; + + if (defined $tt->{'In'}) { + my $ifi = "tmp/test$i.in"; + open X, ">$rundir/$ifi" or die "Unable to create $ifi"; + print X $tt->{'In'}, "\n"; + close X; + $redirs .= " <$ifi"; + } else { + $redirs .= " {'Out'}) { + my $ofi = "tmp/test$i.out"; + unlink "$rundir/$ofi"; + $redirs .= " >$ofi"; + push @out_files, $ofi; + push @out_checks, $tt->{'Out'}; + } else { + $redirs .= " >/dev/null"; + } + foreach my $arg (0..9) { + my $f = "tmp/test$i.$arg"; + if (defined $tt->{"Out$arg"}) { + unlink "$rundir/$f"; + push @out_files, $f; + push @out_checks, $tt->{"Out$arg"}; + } + if (defined $tt->{"In$arg"}) { + open X, ">$rundir/$f" or die "Unable to create $f"; + print X $tt->{"In$arg"}, "\n"; + close X; + } + } + $run =~ s/\$(\d)/tmp\/test$i.$1/g; + print "(running $run) " if $verbose; + system "cd $rundir && ( $run ) $redirs"; + if ($? % 256) { + print "FAILED with status code $?\n"; + $errors++; + next; + } + my $ec = $? / 256; + my $expect_ec = $tt->{'Exit'} || 0; + if ($ec != $expect_ec) { + print "FAILED: unexpected exit code $ec\n"; + $errors++; + next; + } + + for (my $i=0; $i<=$#out_files; $i++) { + my $ofi = $out_files[$i]; + open X, "<$rundir/$ofi" or die "Unable to read $ofi"; + my $out; + { + local $/ = undef; + $out = ; + } + close X; + if ($out ne $out_checks[$i] . "\n") { + print "FAILED (see $ofi)\n"; + $errors++; + next TEST; + } + } + + system "rm -f $rundir/tmp/test$i.*"; + print "OK\n"; +} + +exit !!$errors; -- 2.39.2