* [LTP] [PATCH 3/4] Make system enhancements, Draft 2
@ 2009-07-12 5:42 Garrett Cooper
2009-07-15 16:54 ` Mike Frysinger
0 siblings, 1 reply; 5+ messages in thread
From: Garrett Cooper @ 2009-07-12 5:42 UTC (permalink / raw)
To: LTP list
[-- Attachment #1: Type: text/plain, Size: 20717 bytes --]
A continuation of `[PATCH 2/3] Make system enhancements, Draft 1'.
Summary:
1. Addresses issues brought up by Mike Frysinger.
2. Fixes several bugs found through continued testing.
3. Adds lib.mk, testcases.mk to create more structure in Makefiles,
and prevent ad-hoc structure with libraries and testcases/ directory
binaries to reduce code duplication.
Signed-off-by: Garrett Cooper <yanegomi@gmail.com>
Index: README.mk-devel
===================================================================
RCS file: README.mk-devel
diff -N README.mk-devel
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ README.mk-devel 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,159 @@
+==============================
+Introduction
+==============================
+
+The following document briefly describes the steps and methodologies used for
+the new and improved Makefile system.
+
+==============================
+The Problem
+==============================
+
+The problem with the old Makefile system is that it was very difficult to
+maintain and it lacked any sense of formal structure, thus developing for LTP
+and including new targets was very more difficult than it should have been
+(maintenance). Furthermore, cross-compilation was impossible due to the fact
+that the Makefiles didn't support a prefixing system, and the appropriate
+implicit / static rules hadn't been configured to compile into multiple object
+directories (easy of use / functionality). Finally, there wasn't a means to
+setup dependencies between components, such that if a component required
+libltp.a in order to compile, it would go off and compile libltp.a first
+(easy of use).
+
+These items needed to be fixed to reduce maintenance nightmares for the
+development community contributing to LTP.
+
+==============================
+Design
+==============================
+
+The system was designed such that including a single GNU Makefile compatible
+set in each new directory component is all that's essentially required to
+build the system. Here's an example of how one would accomplish that:
+
+.../foo/Makefile:
+#
+# Copyright disclaimer goes here -- please use GPLv2.
+#
+
+srcdir ?= ../
+
+include $(srcdir)/include/mk/master_include.mk
+
+$(eval $(generic_dir_target))
+
+.../foo/bar/Makefile:
+#
+# Copyright disclaimer goes here -- please use GPLv2.
+#
+
+srcdir ?= ../
+
+include $(srcdir)/include/mk/master_include.mk
+
+$(eval $(generic_leaf_target))
+
+==============================
+Make Rules and Make Variables
+==============================
+
+When using make rules, avoid writing adhoc rules like:
+
+[prog]: [dependencies]
+ cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
+ -o [prog] [dependencies]
+
+etc. This makes cross-compilation and determinism difficult, if not impossible.
+Besides, implicit rules are your friends and as long as you use `MAKEOPTS=;' in
+the top-level caller (or do $(subst r,$(MAKEOPTS)) to remove -r), the compile
+will complete successfully, assuming all other prerequisites have been
+fulfilled (libraries, headers, etc).
+
+$(AR) : The library archiver.
+
+$(CC) : The system C compiler.
+
+$(CXX) : The system C++ compiler.
+
+$(CFLAGS) : Compiler flags.
+
+$(CPPFLAGS) : Preprocessor flags, e.g. -I arguments.
+
+$(DEBUG_CFLAGS) : Debug flags to pass into the C compiler, -g, etc.
+
+$(DEBUG_CXXFLAGS) : Debug flags to pass into the C++ compiler.
+
+$(LD) : The library linker.
+
+$(LDFLAGS) : What to pass in to the linker, including -L arguments
+ and other ld arguments, apart from -l library
+ includes (see $(LDLIBS)).
+
+$(LDLIBS) : Libraries to pass into the linker (e.g. -lltp, etc).
+
+$(OPT_CFLAGS) : Optimization flags to pass into the C compiler, -O2,
+ etc. IF YOU SPECIFY -O2 OR HIGHER, ENSURE THAT YOU
+ ALSO SPECIFY -fno-strict-aliasing, BECAUSE OF PAST
+ OPTIMIZATION GCC BUGS!!!
+
+$(OPT_CXXFLAGS) : Optimization flags to pass into the C++ compiler.
+
+$(RANLIB) : What to run after archiving a library.
+
+$(WCFLAGS) : Warning flags to pass into the C compiler, e.g.
+ -Werror, -Wall, etc.
+
+$(WCXXFLAGS) : Same as $(WCFLAGS), but for the C++ compiler.
+
+==============================
+Make System Variables
+==============================
+
+A series of variables are used within the make system that direct what actions
+need to be taken. Rather than me listing the variables here, please instead
+refer to the comments contained in `.../include/mk/master_rules.mk'.
+
+==============================
+Guidelines and Recommendations
+==============================
+
+Of course, the GNU Make manual is key to understanding the Make system, but
+here are the following sections and chapters I suggest reviewing:
+
+- implicit rules:
http://www.gnu.org/software/make/manual/make.html#Implicit-Rules
+- variables and expansion:
http://www.gnu.org/software/make/manual/make.html#Using-Variables
+- origin use: http://www.gnu.org/software/make/manual/make.html#Origin-Function
+- vpath use: http://www.gnu.org/software/make/manual/make.html#Directory-Search
+
+==============================
+Before Committing
+==============================
+
+One should rebuild from scratch before committing. Here's an example of how to
+do that:
+#!/bin/sh
+
+TOOLS_PATH=/path/to/tools
+
+# Replace [options] with any make specific options and variables, for each
+# step, example: -j 4, DESTDIR=/path/for/install, etc.
+make ac-clean ac-maintainer-clean distclean maintainer-clean [options]
+make \
+ ACLOCAL=$TOOLS_PATH/bin/aclocal \
+ AUTOCONF=$TOOLS_PATH/bin/autoconf \
+ AUTOHEADER=$TOOLS_PATH/bin/autoheader \
+ AUTOMAKE=$TOOLS_PATH/bin/automake \
+ autotools
+./configure [options]
+make all [options]
+make install [options]
+
+==============================
+Other Errata
+==============================
+
+- This system (in its current form) supports cross-compilation out of a single
+directory. Object directory support will be completed soon to properly enable
+cross-compilation. This is required to avoid sporadic Make-related errors.
+
+# vim:
Index: include/mk/master_include.mk
===================================================================
RCS file: include/mk/master_include.mk
diff -N include/mk/master_include.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/master_include.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,25 @@
+#
+# Master include Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+# Only include config.mk for non-clean based targets.
+-include $(top_srcdir)/include/mk/config.mk
+include $(top_srcdir)/include/mk/master_rules.mk
Index: include/mk/master_rules.mk
===================================================================
RCS file: include/mk/master_rules.mk
diff -N include/mk/master_rules.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/master_rules.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,304 @@
+#
+# Master rules Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+# Get the absolute path for the source directory.
+ifeq ($(origin top_srcdir),undefined)
+$(error top_srcdir is not defined)
+endif
+
+# Where's the root source directory?
+top_srcdir := $(abspath $(top_srcdir))
+# Where's the source located at?
+srcdir ?= .
+# Where's the root object directory?
+builddir ?= $(srcdir)
+# Where are we currently located in the object and source tree?
+relpath := $(subst $(abs_builddir),,$(CURDIR))
+# Where are we going to install the files? Most of this junk ends up in
+# testcases/bin, so let's dump it there :)...
+INSTALL_DIR ?= testcases/bin
+
+abs_builddir := $(abspath $(builddir))
+abs_srcdir := $(abspath $(srcdir))
+
+# We can piece together where we're located in the source and object trees with
+# just these two vars and $(CURDIR).
+export top_srcdir builddir
+
+define generate_vpath_rule
+vpath %.$(1) $(if $(2),$(2),$(srcdir))
+endef
+
+define generate_install_rule
+$$(warning "gir: $(1) => $(2)")
+
+$(1):
+ install -m $$(INSTALL_MODE) "$(2)/$$(@F)" "$$@"
+endef
+
+# Default source search path. Modify as necessary, but I would call that
+# poor software design if you need more than one search directory, and
+# would suggest creating a general purpose static library to that end.
+$(eval $(call generate_vpath_rule,c))
+
+#
+# get_make_dirs
+#
+# Sets the make directories in $(SUBDIRS), and then subsequently filters out
+# the subdirectories based on $(FILTER_OUT_DIRS).
+#
+define get_make_dirs
+
+SUBDIRS ?= $$(patsubst %/Makefile,%,$$(wildcard */Makefile))
+
+ifneq ($$(strip $$(SUBDIRS)),) # We have directories to parse.
+ifneq ($$(strip $$(FILTER_OUT_DIRS)),) # We have directories to filter-out.
+SUBDIRS := $$(filter-out $$(FILTER_OUT_DIRS),$$(SUBDIRS))
+endif
+endif
+
+endef
+
+define generic_target_env_setup
+
+ifeq ($$(origin MAKE_TARGETS),undefined)
+MAKE_TARGETS := $$(notdir $$(patsubst %.c,%,$$(wildcard $$(srcdir)/*.c)))
+endif
+
+# Don't append $(MAKE_TARGETS) unless it is non-NUL length.
+ifneq ($$(strip $$(MAKE_TARGETS)),)
+
+CLEAN_TARGETS += $$(MAKE_TARGETS)
+INSTALL_TARGETS += $$(MAKE_TARGETS)
+
+endif
+
+CLEAN_TARGETS += $$(wildcard *.o)
+
+# The large majority of the files that we install are going to be apps and
+# scripts, so let's chmod them like that.
+INSTALL_MODE ?= 00775
+
+ifneq ($(filter-out %install,$(MAKECMDGOALS)),) # Not an install
target -- skip.
+ifeq ($$(origin INSTALL_DIR),undefined) # Not set by the user -- most like a
+ # programming error now in this .mk
+ # file.
+$$(error INSTALL_DIR is not set (undefined))
+else
+ifeq ($$(strip $$(INSTALL_DIR)),) # Set to a NUL-length string (dev
+ # error in a leaf Makefile, or
+ # someone's toying with the
+ # environment).
+$$(error INSTALL_DIR is not set to a non-NUL string)
+ # else $(INSTALL_DIR) is set to a
+ # non-NUL string.
+
+endif # END: INSTALL_DIR NUL-length string.
+endif # END: undefined
+endif # END: Not install
+
+# An absolute path; don't append $(DESTDIR)/$(prefix) to the var.
+ifeq ($$(patsubst /%,,$$(INSTALL_DIR)),)
+INSTALL_PATH := $$(INSTALL_DIR)
+# Otherwise, let's assume that it's not relative to $(prefix)
+else
+INSTALL_PATH := $$(DESTDIR)/$$(prefix)/$$(INSTALL_DIR)
+endif
+
+INSTALL_FILES := $$(addprefix $$(INSTALL_PATH)/,$$(notdir
$$(INSTALL_TARGETS)))
+
+CLEAN_TARGETS += $$(INSTALL_FILES)
+
+$$(INSTALL_PATH):
+ mkdir -p $$@
+
+$$(INSTALL_FILES): %: pre-install $$(abs_builddir)/$$(@F) $$(INSTALL_DEPS)
+ install -m $$(INSTALL_MODE) $$(abs_builddir)/$$(@F) $$@
+
+endef
+
+#
+# generic_leaf_target
+#
+# Generate a set of basic targets (all, clean, install) for a leaf directory
+# (no subdirectories).
+#
+# In order to properly emulate pre- and post- behavior, a pre-install and
+# _install target are generated as well. The flow for install is as follows:
+#
+# pre-install -> $(INSTALL_FILES) -> install
+#
+# Helpful variables are:
+#
+# $(MAKE_DEPS) : What to execute before all.
+# $(MAKE_TARGETS) : What to execute as direct dependencies of
+# all.
+# 1. Defaults to the basename of the targets
+# produced by the %.c -> % implicit pattern
+# rules, e.g. the MAKE_TARGET in a directory
+# like the following:
+#
+# $$ ls /bar
+# foo.c
+#
+# Would be `foo'. Similarly, the following
+# dir structure:
+#
+# $$ ls /bar
+# foo.c zanzibar.c
+#
+# Would be `foo zanzibar'.
+#
+# 2. If you define MAKE_TARGETS as an empty
+# string, this will override the defaults.
+# I did this to avoid providing too much
+# rope to hang one's self in the event of
+# unwanted behavior.
+#
+# $(CLEAN_TARGETS) : What targets should be cleaned (must be
+# real files). This will automatically append
+# adds the .o suffix to all files referenced
+# by $(MAKE_TARGETS)) to CLEAN_TARGETS, if
+# MAKE_TARGETS wasn't defined (see
+# $(MAKE_TARGETS)).
+# $(PREINSTALL_DEPS) : What to run as direct dependencies of
+# pre-install.
+# $(INSTALL_DEPS) : What to run as direct dependencies of
+# the _install target. These must be real
+# files.
+# $(POSTINSTALL_DEPS) : What to install direct dependencies of
+# the install target.
+# $(INSTALL_MODE) : What mode should we using when calling
+# install(1)?
+#
+# If you choose to cherrypick the logic contained here, by changing around the
+# dependencies for $(INSTALL_DEPS) and $(POSTINSTALL_DEPS), then you must also
+# emulate the $(INSTALL_DEPS): pre-install and install: $(POSTINSTALL_DEPS)
+# dependencies, if you _use_ them.
+#
+# Also, if you wish to change the installation directory, from the set default
+# (testcases/bin) you must do something like either one of the following items:
+#
+# Method A:
+#
+# INSTALL_DIR := /path/to/installdir/from/$(DESTDIR)/$(prefix)
+#
+# e.g. if I wanted to install my binaries in testcases/bin, I would do:
+#
+# INSTALL_DIR := testcases/bin
+#
+# in my calling Makefile.
+#
+# Or Method B:
+#
+# INSTALL_DIR := /path/to/installdir/from/$(DESTDIR)
+#
+# e.g. if I wanted to install my binaries in $(libdir) (which may not exist
+# outside of $(prefix) right now, but could in the future), I could do the
+# following:
+#
+# INSTALL_DIR := $(libdir)
+#
+define generic_leaf_target
+
+$$(eval $$(generic_target_env_setup))
+
+.PHONY: all clean _install install pre-install
+
+all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
+
+clean: $$(CLEAN_DEPS)
+ -$(RM) -f $$(CLEAN_TARGETS)
+
+pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
+
+install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
+
+endef
+
+#
+# generic_trunk_target
+#
+# Generate a set of recursive targets to apply over a trunk directory (has
+# directories) -- optionally with a set of trunk-based files.
+#
+# All variables in this canned define are essentially the same as
+# generic_leaf_target, with the exception that the install flow for local
+# targets is:
+#
+# pre-install -> $(INSTALL_FILES) -> trunk-install
+#
+# All recursive targets are traverse SUBDIRS as defined by the user, or if
+# undefined, defaults to any subdirectories where Makefile's are contained
+# within.
+#
+# generic_trunk_target specific variables are:
+#
+# RECURSIVE_TARGETS : a list of targets to apply over an entire
+# directory tree. This defaults to
+# `all clean install'.
+#
+# See generic_leaf_target, generic_target_env_setup, and get_make_dirs for
+# more details and design notes.
+#
+define generic_trunk_target
+
+#
+# Doesn't need forced secondary expansion because $(CURDIR) isn't going to
+# change (or at least it bloody well shouldn't ;)...).
+#
+# Don't do this in generic_target_env_setup, because we only need to do this
+# by default for generic_dir_target.
+#
+$(eval $(get_make_dirs))
+
+RECURSIVE_TARGETS ?= all clean install
+
+.PHONY: $$(RECURSIVE_TARGETS) $$(addprefix
trunk-,$$(RECURSIVE_TARGETS)) pre-install
+
+$$(eval $$(generic_target_env_setup))
+
+trunk-all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
+
+trunk-clean: $$(CLEAN_DEPS)
+ -$(RM) -f $$(CLEAN_TARGETS)
+
+pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
+
+trunk-install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
+
+# Avoid creating duplicate .PHONY references to all, clean, and install. IIRC,
+# I've seen some indeterministic behavior when one does this in the past with
+# GNU Make...
+.PHONY: $$(filter-out $$(RECURSIVE_TARGETS),all clean install)
+all: trunk-all
+
+clean: trunk-clean
+
+install: trunk-install
+
+$$(RECURSIVE_TARGETS): %:
+ @set -e; for dir in $$(SUBDIRS); do \
+ $(MAKE) -C $$$$dir $$@; \
+ done
+
+endef
Index: include/mk/lib.mk
===================================================================
RCS file: include/mk/lib.mk
diff -N include/mk/lib.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/lib.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,71 @@
+#
+# library include Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+include $(top_srcdir)/include/mk/master_include.mk
+
+# Change the default goal when nothing is specified to install because we want
+# to ensure that the libraries get installed ASAP so they can be properly
+# linked in with all required apps.
+CPPFLAGS += -I$(includedir)
+
+# An extension of generic_leaf_target, strictly for libraries.
+define lib_target
+
+.PHONY: install_headers
+
+ifeq ($$(origin LIB),undefined)
+$$(error You must define LIB when including this Makefile)
+endif
+
+install_headers: $$(addprefix $(includedir)/,$$(notdir $$(HEADER_FILES)))
+
+INSTALL_DEPS := install_headers
+
+INSTALL_DIR := $(libdir)
+
+INSTALL_MODE ?= 00664
+
+LIB := $$(addprefix $$(builddir)/,$$(LIB))
+
+MAKE_TARGETS := $$(LIB)
+
+ifeq ($$(origin LIBSRCS),undefined)
+LIBSRCS ?= $$(wildcard $(srcdir)/*.c)
+endif
+
+LIBSRCS := $$(notdir $$(LIBSRCS))
+
+LIBOBJS := $$(addprefix $$(builddir)/,$$(patsubst %.c,%.o,$$(LIBSRCS)))
+
+$$(warning $$(LIBSRCS))
+
+$$(LIB): $$(LIBOBJS)
+ set -e; if [ -z "$$(strip $$^)" ] ; then \
+ echo "Cowardly refusing to create empty archive."; \
+ exit 1; \
+ fi
+ $$(AR) -rc $$@ $$^
+ $$(RANLIB) $$@
+
+$$(eval $$(generic_leaf_target))
+
+endef
Index: include/mk/testcases.mk
===================================================================
RCS file: include/mk/testcases.mk
diff -N include/mk/testcases.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/testcases.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,25 @@
+#
+# testcases include Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+include $(top_srcdir)/include/mk/master_include.mk
+
+LDLIBS += -lltp
[-- Attachment #2: Make-system-enhancements.2.diff --]
[-- Type: application/octet-stream, Size: 20309 bytes --]
Index: README.mk-devel
===================================================================
RCS file: README.mk-devel
diff -N README.mk-devel
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ README.mk-devel 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,159 @@
+==============================
+Introduction
+==============================
+
+The following document briefly describes the steps and methodologies used for
+the new and improved Makefile system.
+
+==============================
+The Problem
+==============================
+
+The problem with the old Makefile system is that it was very difficult to
+maintain and it lacked any sense of formal structure, thus developing for LTP
+and including new targets was very more difficult than it should have been
+(maintenance). Furthermore, cross-compilation was impossible due to the fact
+that the Makefiles didn't support a prefixing system, and the appropriate
+implicit / static rules hadn't been configured to compile into multiple object
+directories (easy of use / functionality). Finally, there wasn't a means to
+setup dependencies between components, such that if a component required
+libltp.a in order to compile, it would go off and compile libltp.a first
+(easy of use).
+
+These items needed to be fixed to reduce maintenance nightmares for the
+development community contributing to LTP.
+
+==============================
+Design
+==============================
+
+The system was designed such that including a single GNU Makefile compatible
+set in each new directory component is all that's essentially required to
+build the system. Here's an example of how one would accomplish that:
+
+.../foo/Makefile:
+#
+# Copyright disclaimer goes here -- please use GPLv2.
+#
+
+srcdir ?= ../
+
+include $(srcdir)/include/mk/master_include.mk
+
+$(eval $(generic_dir_target))
+
+.../foo/bar/Makefile:
+#
+# Copyright disclaimer goes here -- please use GPLv2.
+#
+
+srcdir ?= ../
+
+include $(srcdir)/include/mk/master_include.mk
+
+$(eval $(generic_leaf_target))
+
+==============================
+Make Rules and Make Variables
+==============================
+
+When using make rules, avoid writing adhoc rules like:
+
+[prog]: [dependencies]
+ cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
+ -o [prog] [dependencies]
+
+etc. This makes cross-compilation and determinism difficult, if not impossible.
+Besides, implicit rules are your friends and as long as you use `MAKEOPTS=;' in
+the top-level caller (or do $(subst r,$(MAKEOPTS)) to remove -r), the compile
+will complete successfully, assuming all other prerequisites have been
+fulfilled (libraries, headers, etc).
+
+$(AR) : The library archiver.
+
+$(CC) : The system C compiler.
+
+$(CXX) : The system C++ compiler.
+
+$(CFLAGS) : Compiler flags.
+
+$(CPPFLAGS) : Preprocessor flags, e.g. -I arguments.
+
+$(DEBUG_CFLAGS) : Debug flags to pass into the C compiler, -g, etc.
+
+$(DEBUG_CXXFLAGS) : Debug flags to pass into the C++ compiler.
+
+$(LD) : The library linker.
+
+$(LDFLAGS) : What to pass in to the linker, including -L arguments
+ and other ld arguments, apart from -l library
+ includes (see $(LDLIBS)).
+
+$(LDLIBS) : Libraries to pass into the linker (e.g. -lltp, etc).
+
+$(OPT_CFLAGS) : Optimization flags to pass into the C compiler, -O2,
+ etc. IF YOU SPECIFY -O2 OR HIGHER, ENSURE THAT YOU
+ ALSO SPECIFY -fno-strict-aliasing, BECAUSE OF PAST
+ OPTIMIZATION GCC BUGS!!!
+
+$(OPT_CXXFLAGS) : Optimization flags to pass into the C++ compiler.
+
+$(RANLIB) : What to run after archiving a library.
+
+$(WCFLAGS) : Warning flags to pass into the C compiler, e.g.
+ -Werror, -Wall, etc.
+
+$(WCXXFLAGS) : Same as $(WCFLAGS), but for the C++ compiler.
+
+==============================
+Make System Variables
+==============================
+
+A series of variables are used within the make system that direct what actions
+need to be taken. Rather than me listing the variables here, please instead
+refer to the comments contained in `.../include/mk/master_rules.mk'.
+
+==============================
+Guidelines and Recommendations
+==============================
+
+Of course, the GNU Make manual is key to understanding the Make system, but
+here are the following sections and chapters I suggest reviewing:
+
+- implicit rules: http://www.gnu.org/software/make/manual/make.html#Implicit-Rules
+- variables and expansion: http://www.gnu.org/software/make/manual/make.html#Using-Variables
+- origin use: http://www.gnu.org/software/make/manual/make.html#Origin-Function
+- vpath use: http://www.gnu.org/software/make/manual/make.html#Directory-Search
+
+==============================
+Before Committing
+==============================
+
+One should rebuild from scratch before committing. Here's an example of how to
+do that:
+#!/bin/sh
+
+TOOLS_PATH=/path/to/tools
+
+# Replace [options] with any make specific options and variables, for each
+# step, example: -j 4, DESTDIR=/path/for/install, etc.
+make ac-clean ac-maintainer-clean distclean maintainer-clean [options]
+make \
+ ACLOCAL=$TOOLS_PATH/bin/aclocal \
+ AUTOCONF=$TOOLS_PATH/bin/autoconf \
+ AUTOHEADER=$TOOLS_PATH/bin/autoheader \
+ AUTOMAKE=$TOOLS_PATH/bin/automake \
+ autotools
+./configure [options]
+make all [options]
+make install [options]
+
+==============================
+Other Errata
+==============================
+
+- This system (in its current form) supports cross-compilation out of a single
+directory. Object directory support will be completed soon to properly enable
+cross-compilation. This is required to avoid sporadic Make-related errors.
+
+# vim:
Index: include/mk/master_include.mk
===================================================================
RCS file: include/mk/master_include.mk
diff -N include/mk/master_include.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/master_include.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,25 @@
+#
+# Master include Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+# Only include config.mk for non-clean based targets.
+-include $(top_srcdir)/include/mk/config.mk
+include $(top_srcdir)/include/mk/master_rules.mk
Index: include/mk/master_rules.mk
===================================================================
RCS file: include/mk/master_rules.mk
diff -N include/mk/master_rules.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/master_rules.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,304 @@
+#
+# Master rules Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+# Get the absolute path for the source directory.
+ifeq ($(origin top_srcdir),undefined)
+$(error top_srcdir is not defined)
+endif
+
+# Where's the root source directory?
+top_srcdir := $(abspath $(top_srcdir))
+# Where's the source located at?
+srcdir ?= .
+# Where's the root object directory?
+builddir ?= $(srcdir)
+# Where are we currently located in the object and source tree?
+relpath := $(subst $(abs_builddir),,$(CURDIR))
+# Where are we going to install the files? Most of this junk ends up in
+# testcases/bin, so let's dump it there :)...
+INSTALL_DIR ?= testcases/bin
+
+abs_builddir := $(abspath $(builddir))
+abs_srcdir := $(abspath $(srcdir))
+
+# We can piece together where we're located in the source and object trees with
+# just these two vars and $(CURDIR).
+export top_srcdir builddir
+
+define generate_vpath_rule
+vpath %.$(1) $(if $(2),$(2),$(srcdir))
+endef
+
+define generate_install_rule
+$$(warning "gir: $(1) => $(2)")
+
+$(1):
+ install -m $$(INSTALL_MODE) "$(2)/$$(@F)" "$$@"
+endef
+
+# Default source search path. Modify as necessary, but I would call that
+# poor software design if you need more than one search directory, and
+# would suggest creating a general purpose static library to that end.
+$(eval $(call generate_vpath_rule,c))
+
+#
+# get_make_dirs
+#
+# Sets the make directories in $(SUBDIRS), and then subsequently filters out
+# the subdirectories based on $(FILTER_OUT_DIRS).
+#
+define get_make_dirs
+
+SUBDIRS ?= $$(patsubst %/Makefile,%,$$(wildcard */Makefile))
+
+ifneq ($$(strip $$(SUBDIRS)),) # We have directories to parse.
+ifneq ($$(strip $$(FILTER_OUT_DIRS)),) # We have directories to filter-out.
+SUBDIRS := $$(filter-out $$(FILTER_OUT_DIRS),$$(SUBDIRS))
+endif
+endif
+
+endef
+
+define generic_target_env_setup
+
+ifeq ($$(origin MAKE_TARGETS),undefined)
+MAKE_TARGETS := $$(notdir $$(patsubst %.c,%,$$(wildcard $$(srcdir)/*.c)))
+endif
+
+# Don't append $(MAKE_TARGETS) unless it is non-NUL length.
+ifneq ($$(strip $$(MAKE_TARGETS)),)
+
+CLEAN_TARGETS += $$(MAKE_TARGETS)
+INSTALL_TARGETS += $$(MAKE_TARGETS)
+
+endif
+
+CLEAN_TARGETS += $$(wildcard *.o)
+
+# The large majority of the files that we install are going to be apps and
+# scripts, so let's chmod them like that.
+INSTALL_MODE ?= 00775
+
+ifneq ($(filter-out %install,$(MAKECMDGOALS)),) # Not an install target -- skip.
+ifeq ($$(origin INSTALL_DIR),undefined) # Not set by the user -- most like a
+ # programming error now in this .mk
+ # file.
+$$(error INSTALL_DIR is not set (undefined))
+else
+ifeq ($$(strip $$(INSTALL_DIR)),) # Set to a NUL-length string (dev
+ # error in a leaf Makefile, or
+ # someone's toying with the
+ # environment).
+$$(error INSTALL_DIR is not set to a non-NUL string)
+ # else $(INSTALL_DIR) is set to a
+ # non-NUL string.
+
+endif # END: INSTALL_DIR NUL-length string.
+endif # END: undefined
+endif # END: Not install
+
+# An absolute path; don't append $(DESTDIR)/$(prefix) to the var.
+ifeq ($$(patsubst /%,,$$(INSTALL_DIR)),)
+INSTALL_PATH := $$(INSTALL_DIR)
+# Otherwise, let's assume that it's not relative to $(prefix)
+else
+INSTALL_PATH := $$(DESTDIR)/$$(prefix)/$$(INSTALL_DIR)
+endif
+
+INSTALL_FILES := $$(addprefix $$(INSTALL_PATH)/,$$(notdir $$(INSTALL_TARGETS)))
+
+CLEAN_TARGETS += $$(INSTALL_FILES)
+
+$$(INSTALL_PATH):
+ mkdir -p $$@
+
+$$(INSTALL_FILES): %: pre-install $$(abs_builddir)/$$(@F) $$(INSTALL_DEPS)
+ install -m $$(INSTALL_MODE) $$(abs_builddir)/$$(@F) $$@
+
+endef
+
+#
+# generic_leaf_target
+#
+# Generate a set of basic targets (all, clean, install) for a leaf directory
+# (no subdirectories).
+#
+# In order to properly emulate pre- and post- behavior, a pre-install and
+# _install target are generated as well. The flow for install is as follows:
+#
+# pre-install -> $(INSTALL_FILES) -> install
+#
+# Helpful variables are:
+#
+# $(MAKE_DEPS) : What to execute before all.
+# $(MAKE_TARGETS) : What to execute as direct dependencies of
+# all.
+# 1. Defaults to the basename of the targets
+# produced by the %.c -> % implicit pattern
+# rules, e.g. the MAKE_TARGET in a directory
+# like the following:
+#
+# $$ ls /bar
+# foo.c
+#
+# Would be `foo'. Similarly, the following
+# dir structure:
+#
+# $$ ls /bar
+# foo.c zanzibar.c
+#
+# Would be `foo zanzibar'.
+#
+# 2. If you define MAKE_TARGETS as an empty
+# string, this will override the defaults.
+# I did this to avoid providing too much
+# rope to hang one's self in the event of
+# unwanted behavior.
+#
+# $(CLEAN_TARGETS) : What targets should be cleaned (must be
+# real files). This will automatically append
+# adds the .o suffix to all files referenced
+# by $(MAKE_TARGETS)) to CLEAN_TARGETS, if
+# MAKE_TARGETS wasn't defined (see
+# $(MAKE_TARGETS)).
+# $(PREINSTALL_DEPS) : What to run as direct dependencies of
+# pre-install.
+# $(INSTALL_DEPS) : What to run as direct dependencies of
+# the _install target. These must be real
+# files.
+# $(POSTINSTALL_DEPS) : What to install direct dependencies of
+# the install target.
+# $(INSTALL_MODE) : What mode should we using when calling
+# install(1)?
+#
+# If you choose to cherrypick the logic contained here, by changing around the
+# dependencies for $(INSTALL_DEPS) and $(POSTINSTALL_DEPS), then you must also
+# emulate the $(INSTALL_DEPS): pre-install and install: $(POSTINSTALL_DEPS)
+# dependencies, if you _use_ them.
+#
+# Also, if you wish to change the installation directory, from the set default
+# (testcases/bin) you must do something like either one of the following items:
+#
+# Method A:
+#
+# INSTALL_DIR := /path/to/installdir/from/$(DESTDIR)/$(prefix)
+#
+# e.g. if I wanted to install my binaries in testcases/bin, I would do:
+#
+# INSTALL_DIR := testcases/bin
+#
+# in my calling Makefile.
+#
+# Or Method B:
+#
+# INSTALL_DIR := /path/to/installdir/from/$(DESTDIR)
+#
+# e.g. if I wanted to install my binaries in $(libdir) (which may not exist
+# outside of $(prefix) right now, but could in the future), I could do the
+# following:
+#
+# INSTALL_DIR := $(libdir)
+#
+define generic_leaf_target
+
+$$(eval $$(generic_target_env_setup))
+
+.PHONY: all clean _install install pre-install
+
+all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
+
+clean: $$(CLEAN_DEPS)
+ -$(RM) -f $$(CLEAN_TARGETS)
+
+pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
+
+install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
+
+endef
+
+#
+# generic_trunk_target
+#
+# Generate a set of recursive targets to apply over a trunk directory (has
+# directories) -- optionally with a set of trunk-based files.
+#
+# All variables in this canned define are essentially the same as
+# generic_leaf_target, with the exception that the install flow for local
+# targets is:
+#
+# pre-install -> $(INSTALL_FILES) -> trunk-install
+#
+# All recursive targets are traverse SUBDIRS as defined by the user, or if
+# undefined, defaults to any subdirectories where Makefile's are contained
+# within.
+#
+# generic_trunk_target specific variables are:
+#
+# RECURSIVE_TARGETS : a list of targets to apply over an entire
+# directory tree. This defaults to
+# `all clean install'.
+#
+# See generic_leaf_target, generic_target_env_setup, and get_make_dirs for
+# more details and design notes.
+#
+define generic_trunk_target
+
+#
+# Doesn't need forced secondary expansion because $(CURDIR) isn't going to
+# change (or at least it bloody well shouldn't ;)...).
+#
+# Don't do this in generic_target_env_setup, because we only need to do this
+# by default for generic_dir_target.
+#
+$(eval $(get_make_dirs))
+
+RECURSIVE_TARGETS ?= all clean install
+
+.PHONY: $$(RECURSIVE_TARGETS) $$(addprefix trunk-,$$(RECURSIVE_TARGETS)) pre-install
+
+$$(eval $$(generic_target_env_setup))
+
+trunk-all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
+
+trunk-clean: $$(CLEAN_DEPS)
+ -$(RM) -f $$(CLEAN_TARGETS)
+
+pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
+
+trunk-install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
+
+# Avoid creating duplicate .PHONY references to all, clean, and install. IIRC,
+# I've seen some indeterministic behavior when one does this in the past with
+# GNU Make...
+.PHONY: $$(filter-out $$(RECURSIVE_TARGETS),all clean install)
+all: trunk-all
+
+clean: trunk-clean
+
+install: trunk-install
+
+$$(RECURSIVE_TARGETS): %:
+ @set -e; for dir in $$(SUBDIRS); do \
+ $(MAKE) -C $$$$dir $$@; \
+ done
+
+endef
Index: include/mk/lib.mk
===================================================================
RCS file: include/mk/lib.mk
diff -N include/mk/lib.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/lib.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,71 @@
+#
+# library include Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+include $(top_srcdir)/include/mk/master_include.mk
+
+# Change the default goal when nothing is specified to install because we want
+# to ensure that the libraries get installed ASAP so they can be properly
+# linked in with all required apps.
+CPPFLAGS += -I$(includedir)
+
+# An extension of generic_leaf_target, strictly for libraries.
+define lib_target
+
+.PHONY: install_headers
+
+ifeq ($$(origin LIB),undefined)
+$$(error You must define LIB when including this Makefile)
+endif
+
+install_headers: $$(addprefix $(includedir)/,$$(notdir $$(HEADER_FILES)))
+
+INSTALL_DEPS := install_headers
+
+INSTALL_DIR := $(libdir)
+
+INSTALL_MODE ?= 00664
+
+LIB := $$(addprefix $$(builddir)/,$$(LIB))
+
+MAKE_TARGETS := $$(LIB)
+
+ifeq ($$(origin LIBSRCS),undefined)
+LIBSRCS ?= $$(wildcard $(srcdir)/*.c)
+endif
+
+LIBSRCS := $$(notdir $$(LIBSRCS))
+
+LIBOBJS := $$(addprefix $$(builddir)/,$$(patsubst %.c,%.o,$$(LIBSRCS)))
+
+$$(warning $$(LIBSRCS))
+
+$$(LIB): $$(LIBOBJS)
+ set -e; if [ -z "$$(strip $$^)" ] ; then \
+ echo "Cowardly refusing to create empty archive."; \
+ exit 1; \
+ fi
+ $$(AR) -rc $$@ $$^
+ $$(RANLIB) $$@
+
+$$(eval $$(generic_leaf_target))
+
+endef
Index: include/mk/testcases.mk
===================================================================
RCS file: include/mk/testcases.mk
diff -N include/mk/testcases.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mk/testcases.mk 12 Jul 2009 05:38:40 -0000
@@ -0,0 +1,25 @@
+#
+# testcases include Makefile.
+#
+# Copyright (C) 2009, Cisco Systems Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Garrett Cooper, July 2009
+#
+
+include $(top_srcdir)/include/mk/master_include.mk
+
+LDLIBS += -lltp
[-- Attachment #3: Type: text/plain, Size: 389 bytes --]
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
[-- Attachment #4: Type: text/plain, Size: 155 bytes --]
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [LTP] [PATCH 3/4] Make system enhancements, Draft 2
2009-07-12 5:42 [LTP] [PATCH 3/4] Make system enhancements, Draft 2 Garrett Cooper
@ 2009-07-15 16:54 ` Mike Frysinger
2009-07-18 21:08 ` Garrett Cooper
0 siblings, 1 reply; 5+ messages in thread
From: Mike Frysinger @ 2009-07-15 16:54 UTC (permalink / raw)
To: ltp-list
[-- Attachment #1.1: Type: text/plain, Size: 2925 bytes --]
On Sunday 12 July 2009 01:42:03 Garrett Cooper wrote:
> +$(CC) : The system C compiler.
> +
> +$(CXX) : The system C++ compiler.
should add $(CPP) - the system preprocessor
> +$(CFLAGS) : Compiler flags.
C compiler flags
should add $(CXXFLAGS) too
> +$(LD) : The library linker.
the system linker (typically $(CC))
> +$(LDFLAGS) : What to pass in to the linker, including -L arguments
> + and other ld arguments, apart from -l library
> + includes (see $(LDLIBS)).
should note that flags should be in the form given to the compiler driver
because we arent invoking `ld` -- i.e. -Wl,-foo not -foo
> +$(LDLIBS) : Libraries to pass into the linker (e.g. -lltp, etc).
s/into/to/
> +$(OPT_CFLAGS) : Optimization flags to pass into the C compiler, -O2,
> + etc. IF YOU SPECIFY -O2 OR HIGHER, ENSURE THAT YOU
> + ALSO SPECIFY -fno-strict-aliasing, BECAUSE OF PAST
> + OPTIMIZATION GCC BUGS!!!
tr '[:upper:]' '[:lower:]'
do you have any actual examples of this ?
> +$(OPT_CXXFLAGS) : Optimization flags to pass into the C++ compiler.
s/into/to/
> +$(RANLIB) : What to run after archiving a library.
the archive indexer
> +# Replace [options] with any make specific options and variables, for each
> +# step, example: -j 4, DESTDIR=/path/for/install, etc.
> +make ac-clean ac-maintainer-clean distclean maintainer-clean [options]
there should be no need to run these targets. "maintainer-clean" should imply
all of these other targets.
> +==============================
> +Other Errata
> +==============================
> +
> +- This system (in its current form) supports cross-compilation out of a
> single +directory. Object directory support will be completed soon to
> properly enable +cross-compilation. This is required to avoid sporadic
> Make-related errors.
i have no idea what you're talking about here
> +# Where's the root source directory?
> +top_srcdir := $(abspath $(top_srcdir))
> +# Where's the source located at?
> +srcdir ?= .
> +# Where's the root object directory?
> +builddir ?= $(srcdir)
need a top_builddir too
> +# Where are we currently located in the object and source tree?
> +relpath := $(subst $(abs_builddir),,$(CURDIR))
is this actually necessary ?
> +all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
> +
> +clean: $$(CLEAN_DEPS)
> + -$(RM) -f $$(CLEAN_TARGETS)
> +
> +pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
> +
> +install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
so why do we need these _DEPS vars ? do you need the $(MAKE_DEPS) to be
processed before $(MAKE_TARGETS) ?
at least for the clean target, it'd be easier to write it:
clean::
$(RM) -f $$(CLEAN_TARGETS)
and then people can just define their own "clean::" in their makefile to do
whatever they want. be nice if we could use this method for all the targets.
-mike
[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 389 bytes --]
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
[-- Attachment #3: Type: text/plain, Size: 155 bytes --]
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [LTP] [PATCH 3/4] Make system enhancements, Draft 2
2009-07-15 16:54 ` Mike Frysinger
@ 2009-07-18 21:08 ` Garrett Cooper
2009-07-18 22:45 ` Mike Frysinger
0 siblings, 1 reply; 5+ messages in thread
From: Garrett Cooper @ 2009-07-18 21:08 UTC (permalink / raw)
To: Mike Frysinger; +Cc: ltp-list
On Wed, Jul 15, 2009 at 9:54 AM, Mike Frysinger<vapier@gentoo.org> wrote:
> On Sunday 12 July 2009 01:42:03 Garrett Cooper wrote:
>> +$(CC) : The system C compiler.
>> +
>> +$(CXX) : The system C++ compiler.
>
> should add $(CPP) - the system preprocessor
Done.
>> +$(CFLAGS) : Compiler flags.
>
> C compiler flags
>
> should add $(CXXFLAGS) too
Done.
>> +$(LD) : The library linker.
>
> the system linker (typically $(CC))
Here's what I said (instead of the above):
$(LD) : The system linker (typically $(CC), but not
necessarily).
>> +$(LDFLAGS) : What to pass in to the linker, including -L arguments
>> + and other ld arguments, apart from -l library
>> + includes (see $(LDLIBS)).
>
> should note that flags should be in the form given to the compiler driver
> because we arent invoking `ld` -- i.e. -Wl,-foo not -foo
Similar to above...
$(LDFLAGS) : What to pass in to the linker, including -L arguments
and other ld arguments, apart from -l library
includes (see $(LDLIBS)).
This should be done in the $(CC) args passing style
when LD := $(CC), e.g. `-Wl,-foo', as opposed to
`-foo'
>> +$(LDLIBS) : Libraries to pass into the linker (e.g. -lltp, etc).
>
> s/into/to/
Done. All other instances where I used into instead of to have been
fixed as well.
>> +$(OPT_CFLAGS) : Optimization flags to pass into the C compiler, -O2,
>> + etc. IF YOU SPECIFY -O2 OR HIGHER, ENSURE THAT YOU
>> + ALSO SPECIFY -fno-strict-aliasing, BECAUSE OF PAST
>> + OPTIMIZATION GCC BUGS!!!
>
> tr '[:upper:]' '[:lower:]'
>
> do you have any actual examples of this ?
Fixed the all-caps.
Yes, there are a ton, but here are the two most recent ones I brought up:
1. tree-optimization/17510
2. tree-optimization/39100
Needless to say the gcc folks have not been able to get a stable
tree-optimization checker for more than 2 minor releases from what I'm
seeing.. these bugs have cropped up since 3.3.x, and have appeared in
4.0, 4.2.x (IIRC -- 4.2.1 is the FreeBSD system C compiler), and have
popped up in 4.4. They generally have been fixed swiftly and without
remorse, but for the sake of sanity, the suggestion still stands to
always use -fno-strict-aliasing from FreeBSD, as well as other
software groups due to compiler bugs.
I agree though, if a compiler is sound, using -fstrict-aliasing
should, and could produce broken code if it is indeed broken code --
again, unfortunately the tree optimizer hasn't remained stable long
enough for that to remain the defacto standard.
>> +$(OPT_CXXFLAGS) : Optimization flags to pass into the C++ compiler.
>
> s/into/to/
Done.
>> +$(RANLIB) : What to run after archiving a library.
>
> the archive indexer
Done.
>> +# Replace [options] with any make specific options and variables, for each
>> +# step, example: -j 4, DESTDIR=/path/for/install, etc.
>> +make ac-clean ac-maintainer-clean distclean maintainer-clean [options]
>
> there should be no need to run these targets. "maintainer-clean" should imply
> all of these other targets.
Done. Thanks for the note :)!
>> +==============================
>> +Other Errata
>> +==============================
>> +
>> +- This system (in its current form) supports cross-compilation out of a
>> single +directory. Object directory support will be completed soon to
>> properly enable +cross-compilation. This is required to avoid sporadic
>> Make-related errors.
>
> i have no idea what you're talking about here
The first phase of the work was to resolve outstanding issues with
structure. Then after that's fixed the whole objects being produced in
the same directory as the source files issue can be resolved, THUS my
group can finally build two different copies of LTP _in-parallel_,
with the same workspace, provided they specify the right variables in
their make call.
>> +# Where's the root source directory?
>> +top_srcdir := $(abspath $(top_srcdir))
>> +# Where's the source located at?
>> +srcdir ?= .
>> +# Where's the root object directory?
>> +builddir ?= $(srcdir)
>
> need a top_builddir too
Ah, good catch. Done.
>> +# Where are we currently located in the object and source tree?
>> +relpath := $(subst $(abs_builddir),,$(CURDIR))
>
> is this actually necessary ?
relpath is what calculates how to make it back up the tree (basically
calculating top_builddir, on the fly I suppose)... probably isn't
needed now though.
>> +all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
>> +
>> +clean: $$(CLEAN_DEPS)
>> + -$(RM) -f $$(CLEAN_TARGETS)
>> +
>> +pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
>> +
>> +install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
>
> so why do we need these _DEPS vars ? do you need the $(MAKE_DEPS) to be
> processed before $(MAKE_TARGETS) ?
Yes. The point is to force in-order dependencies, e.g.
If I need to install a file, I'll do a bunch of prereq steps first,
then once they all complete, I'll go on to generate the file and
install it.
> at least for the clean target, it'd be easier to write it:
> clean::
> $(RM) -f $$(CLEAN_TARGETS)
Yeah, that's true. It just makes specifying the recursive targets a
PITA (can't mix :: with :), but then again all recursive targets
should have a clean. If not, they're broken.
> and then people can just define their own "clean::" in their makefile to do
> whatever they want. be nice if we could use this method for all the targets.
Yeah, but that was the point of *_DEPS.
*_DEPS is for PHONY targets.
*_TARGETS is for _real_ files.
The purpose is that PHONY targets are always executed -- something
that may or may not be a good idea, but it forces evaluation and
regeneration on the fly, which can be a big plus for what we're trying
to accomplish as far as generating a series of files is concerned
(testcases/kernel/include's regen target, for example).
You can define MAKE_TARGETS generation, based on an actual target, but
the point was to ween people off of Makefiles that are all over the
map as far as style goes because it makes maintenance a serious PITA.
If they _really_ want that behavior anyhow, they can always just
completely skip defining MAKE_DEPS, as it will evaluate to an empty
value :).
HTH and Thanks!
-Garrett
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [LTP] [PATCH 3/4] Make system enhancements, Draft 2
2009-07-18 21:08 ` Garrett Cooper
@ 2009-07-18 22:45 ` Mike Frysinger
2009-07-18 23:19 ` Garrett Cooper
0 siblings, 1 reply; 5+ messages in thread
From: Mike Frysinger @ 2009-07-18 22:45 UTC (permalink / raw)
To: Garrett Cooper; +Cc: ltp-list
[-- Attachment #1.1: Type: text/plain, Size: 7444 bytes --]
On Saturday 18 July 2009 17:08:50 Garrett Cooper wrote:
> On Wed, Jul 15, 2009 at 9:54 AM, Mike Frysinger<vapier@gentoo.org> wrote:
> > On Sunday 12 July 2009 01:42:03 Garrett Cooper wrote:
> >> +$(LD) : The library linker.
> >
> > the system linker (typically $(CC))
>
> Here's what I said (instead of the above):
>
> $(LD) : The system linker (typically $(CC), but not
> necessarily).
The system linker (this *should* be the same as $(CC))
i cant think of any reason that the source would *need* to invoke `ld`
directly rather than letting `gcc` do the linking, but i can think of many
cases where doing so will screw up edge cases. we should fix places that
invoke `ld` directly.
> >> +$(OPT_CFLAGS) : Optimization flags to pass into the C
> >> compiler, -O2, + etc. IF YOU SPECIFY -O2 OR
> >> HIGHER, ENSURE THAT YOU + ALSO SPECIFY
> >> -fno-strict-aliasing, BECAUSE OF PAST +
> >> OPTIMIZATION GCC BUGS!!!
> >
> > tr '[:upper:]' '[:lower:]'
> >
> > do you have any actual examples of this ?
>
> Yes, there are a ton, but here are the two most recent ones I brought up:
>
> 1. tree-optimization/17510
> 2. tree-optimization/39100
>
> Needless to say the gcc folks have not been able to get a stable
> tree-optimization checker for more than 2 minor releases from what I'm
> seeing.. these bugs have cropped up since 3.3.x, and have appeared in
> 4.0, 4.2.x (IIRC -- 4.2.1 is the FreeBSD system C compiler), and have
> popped up in 4.4. They generally have been fixed swiftly and without
> remorse, but for the sake of sanity, the suggestion still stands to
> always use -fno-strict-aliasing from FreeBSD, as well as other
> software groups due to compiler bugs.
the software groups i see that recommend that do so because their code is
broken and they havent figured out how to fix it properly yet
> I agree though, if a compiler is sound, using -fstrict-aliasing
> should, and could produce broken code if it is indeed broken code --
> again, unfortunately the tree optimizer hasn't remained stable long
> enough for that to remain the defacto standard.
sounds like the FreeBSD guys just keep picking the wrong major versions. 4.0
and 4.2 were awful choices -- many distros simply skipped them because they
had so many bugs in general. that is why most Linux distros went 3.4 -> 4.1 -
> 4.3.
i would change the warning to include the word "should"
> >> +==============================
> >> +Other Errata
> >> +==============================
> >> +
> >> +- This system (in its current form) supports cross-compilation out of a
> >> single +directory. Object directory support will be completed soon to
> >> properly enable +cross-compilation. This is required to avoid sporadic
> >> Make-related errors.
> >
> > i have no idea what you're talking about here
>
> The first phase of the work was to resolve outstanding issues with
> structure. Then after that's fixed the whole objects being produced in
> the same directory as the source files issue can be resolved, THUS my
> group can finally build two different copies of LTP _in-parallel_,
> with the same workspace, provided they specify the right variables in
> their make call.
yes, but i dont see how full out-of-tree build support is related to (1)
"properly enable cross-compilation" or (2) "avoid sporadic Make-related
errors". cross-compilation is supported today already and i dont see your
patches changing that. i dont see any sporadic make-related errors either
today, and your patch shouldnt change that.
or are you just being pessimistic that your patches will break some edge case
Makefiles ?
> >> +# Where are we currently located in the object and source tree?
> >> +relpath := $(subst
> >> $(abs_builddir),,$(CURDIR))
> >
> > is this actually necessary ?
>
> relpath is what calculates how to make it back up the tree (basically
> calculating top_builddir, on the fly I suppose)... probably isn't
> needed now though.
i also couldnt seem to find any references to $(relpath) ...
> >> +all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
> >> +
> >> +clean: $$(CLEAN_DEPS)
> >> + -$(RM) -f $$(CLEAN_TARGETS)
> >> +
> >> +pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
> >> +
> >> +install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
> >
> > so why do we need these _DEPS vars ? do you need the $(MAKE_DEPS) to be
> > processed before $(MAKE_TARGETS) ?
>
> Yes. The point is to force in-order dependencies, e.g.
>
> If I need to install a file, I'll do a bunch of prereq steps first,
> then once they all complete, I'll go on to generate the file and
> install it.
i dont think make operates the way you're expecting. the form is:
targets : prerequisites | order-only prerequisites
and the dependencies of the targets can be processed in parallel. so by
putting the deps and the targets together, you've said make may process those
in parallel if it so chooses ... which sort of defeats the point. and the
prerequisite part means any updated dependencies do not force updating of the
targets in question ... which might be your intention ...
i think you actually want:
$(MAKE_TARGETS): | $(MAKE_DEPS)
> > at least for the clean target, it'd be easier to write it:
> > clean::
> > $(RM) -f $$(CLEAN_TARGETS)
>
> Yeah, that's true. It just makes specifying the recursive targets a
> PITA (can't mix :: with :), but then again all recursive targets
> should have a clean. If not, they're broken.
using double colon rules should hopefully allow us to be more proactive in
weeding out these bad apples though right ?
> > and then people can just define their own "clean::" in their makefile to
> > do whatever they want. be nice if we could use this method for all the
> > targets.
>
> Yeah, but that was the point of *_DEPS.
>
> *_DEPS is for PHONY targets.
> *_TARGETS is for _real_ files.
these notes should be in the .mk file as well
> The purpose is that PHONY targets are always executed -- something
> that may or may not be a good idea, but it forces evaluation and
> regeneration on the fly, which can be a big plus for what we're trying
> to accomplish as far as generating a series of files is concerned
> (testcases/kernel/include's regen target, for example).
i think you misinterpret the point of the regen target. it exists so i could
run `make regen` regardless of dependencies (i.e. *force* a regen). it does
not come into play at any other time though -- the normal `make` should not
force a regeneration of the header file unless the dependencies were updated.
> You can define MAKE_TARGETS generation, based on an actual target, but
> the point was to ween people off of Makefiles that are all over the
> map as far as style goes because it makes maintenance a serious PITA.
>
> If they _really_ want that behavior anyhow, they can always just
> completely skip defining MAKE_DEPS, as it will evaluate to an empty
> value :).
i guess we can do the conversion of the tree and then go back and evaluate if
these _DEPS are truly necessary, and if so, how we can architect them in
simpler terms.
-mike
[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 389 bytes --]
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
[-- Attachment #3: Type: text/plain, Size: 155 bytes --]
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [LTP] [PATCH 3/4] Make system enhancements, Draft 2
2009-07-18 22:45 ` Mike Frysinger
@ 2009-07-18 23:19 ` Garrett Cooper
0 siblings, 0 replies; 5+ messages in thread
From: Garrett Cooper @ 2009-07-18 23:19 UTC (permalink / raw)
To: Mike Frysinger; +Cc: ltp-list
On Sat, Jul 18, 2009 at 3:45 PM, Mike Frysinger<vapier@gentoo.org> wrote:
> On Saturday 18 July 2009 17:08:50 Garrett Cooper wrote:
>> On Wed, Jul 15, 2009 at 9:54 AM, Mike Frysinger<vapier@gentoo.org> wrote:
>> > On Sunday 12 July 2009 01:42:03 Garrett Cooper wrote:
>> >> +$(LD) : The library linker.
>> >
>> > the system linker (typically $(CC))
>>
>> Here's what I said (instead of the above):
>>
>> $(LD) : The system linker (typically $(CC), but not
>> necessarily).
>
> The system linker (this *should* be the same as $(CC))
>
> i cant think of any reason that the source would *need* to invoke `ld`
> directly rather than letting `gcc` do the linking, but i can think of many
> cases where doing so will screw up edge cases. we should fix places that
> invoke `ld` directly.
This doesn't happen anywhere today, thankfully. I'll change the comment then.
>> >> +$(OPT_CFLAGS) : Optimization flags to pass into the C
>> >> compiler, -O2, + etc. IF YOU SPECIFY -O2 OR
>> >> HIGHER, ENSURE THAT YOU + ALSO SPECIFY
>> >> -fno-strict-aliasing, BECAUSE OF PAST +
>> >> OPTIMIZATION GCC BUGS!!!
>> >
>> > tr '[:upper:]' '[:lower:]'
>> >
>> > do you have any actual examples of this ?
>>
>> Yes, there are a ton, but here are the two most recent ones I brought up:
>>
>> 1. tree-optimization/17510
>> 2. tree-optimization/39100
>>
>> Needless to say the gcc folks have not been able to get a stable
>> tree-optimization checker for more than 2 minor releases from what I'm
>> seeing.. these bugs have cropped up since 3.3.x, and have appeared in
>> 4.0, 4.2.x (IIRC -- 4.2.1 is the FreeBSD system C compiler), and have
>> popped up in 4.4. They generally have been fixed swiftly and without
>> remorse, but for the sake of sanity, the suggestion still stands to
>> always use -fno-strict-aliasing from FreeBSD, as well as other
>> software groups due to compiler bugs.
>
> the software groups i see that recommend that do so because their code is
> broken and they havent figured out how to fix it properly yet
Yeah, perhaps.
>> I agree though, if a compiler is sound, using -fstrict-aliasing
>> should, and could produce broken code if it is indeed broken code --
>> again, unfortunately the tree optimizer hasn't remained stable long
>> enough for that to remain the defacto standard.
>
> sounds like the FreeBSD guys just keep picking the wrong major versions. 4.0
> and 4.2 were awful choices -- many distros simply skipped them because they
> had so many bugs in general. that is why most Linux distros went 3.4 -> 4.1 -
>> 4.3.
Well, they haven't (and most likely won't) jump to 4.3+ for licensing
reasons, but that's a different story for a different forum.
> i would change the warning to include the word "should"
Ok.
>> >> +==============================
>> >> +Other Errata
>> >> +==============================
>> >> +
>> >> +- This system (in its current form) supports cross-compilation out of a
>> >> single +directory. Object directory support will be completed soon to
>> >> properly enable +cross-compilation. This is required to avoid sporadic
>> >> Make-related errors.
>> >
>> > i have no idea what you're talking about here
>>
>> The first phase of the work was to resolve outstanding issues with
>> structure. Then after that's fixed the whole objects being produced in
>> the same directory as the source files issue can be resolved, THUS my
>> group can finally build two different copies of LTP _in-parallel_,
>> with the same workspace, provided they specify the right variables in
>> their make call.
>
> yes, but i dont see how full out-of-tree build support is related to (1)
> "properly enable cross-compilation" or (2) "avoid sporadic Make-related
> errors". cross-compilation is supported today already and i dont see your
> patches changing that. i dont see any sporadic make-related errors either
> today, and your patch shouldnt change that.
Yeah, I meant out-of-tree build support... I keep on mixing those two
terms up -_-...
> or are you just being pessimistic that your patches will break some edge case
> Makefiles ?
Eh? I'm making sure that it doesn't by testing beforehand, but yes,
there's some fixing that will follow after these are completed.
>> >> +# Where are we currently located in the object and source tree?
>> >> +relpath := $(subst
>> >> $(abs_builddir),,$(CURDIR))
>> >
>> > is this actually necessary ?
>>
>> relpath is what calculates how to make it back up the tree (basically
>> calculating top_builddir, on the fly I suppose)... probably isn't
>> needed now though.
>
> i also couldnt seem to find any references to $(relpath) ...
I nuked it.
>> >> +all: | $$(MAKE_DEPS) $$(MAKE_TARGETS)
>> >> +
>> >> +clean: $$(CLEAN_DEPS)
>> >> + -$(RM) -f $$(CLEAN_TARGETS)
>> >> +
>> >> +pre-install: | $$(INSTALL_PATH) $$(PREINSTALL_DEPS)
>> >> +
>> >> +install: | $$(INSTALL_FILES) $$(POSTINSTALL_DEPS)
>> >
>> > so why do we need these _DEPS vars ? do you need the $(MAKE_DEPS) to be
>> > processed before $(MAKE_TARGETS) ?
>>
>> Yes. The point is to force in-order dependencies, e.g.
>>
>> If I need to install a file, I'll do a bunch of prereq steps first,
>> then once they all complete, I'll go on to generate the file and
>> install it.
>
> i dont think make operates the way you're expecting. the form is:
> targets : prerequisites | order-only prerequisites
>
> and the dependencies of the targets can be processed in parallel. so by
> putting the deps and the targets together, you've said make may process those
> in parallel if it so chooses ... which sort of defeats the point. and the
> prerequisite part means any updated dependencies do not force updating of the
> targets in question ... which might be your intention ...
>
> i think you actually want:
> $(MAKE_TARGETS): | $(MAKE_DEPS)
Hrmmmm... ok. I was goofing it up from the start then ><.. thanks for
the clarification on that.
>> > at least for the clean target, it'd be easier to write it:
>> > clean::
>> > $(RM) -f $$(CLEAN_TARGETS)
>>
>> Yeah, that's true. It just makes specifying the recursive targets a
>> PITA (can't mix :: with :), but then again all recursive targets
>> should have a clean. If not, they're broken.
>
> using double colon rules should hopefully allow us to be more proactive in
> weeding out these bad apples though right ?
True, but in the beginning it's going to be wide-spread breakage.
>> > and then people can just define their own "clean::" in their makefile to
>> > do whatever they want. be nice if we could use this method for all the
>> > targets.
>>
>> Yeah, but that was the point of *_DEPS.
>>
>> *_DEPS is for PHONY targets.
>> *_TARGETS is for _real_ files.
>
> these notes should be in the .mk file as well
Ok.
>> The purpose is that PHONY targets are always executed -- something
>> that may or may not be a good idea, but it forces evaluation and
>> regeneration on the fly, which can be a big plus for what we're trying
>> to accomplish as far as generating a series of files is concerned
>> (testcases/kernel/include's regen target, for example).
>
> i think you misinterpret the point of the regen target. it exists so i could
> run `make regen` regardless of dependencies (i.e. *force* a regen). it does
> not come into play at any other time though -- the normal `make` should not
> force a regeneration of the header file unless the dependencies were updated.
Yeah, I suppose so.
>> You can define MAKE_TARGETS generation, based on an actual target, but
>> the point was to ween people off of Makefiles that are all over the
>> map as far as style goes because it makes maintenance a serious PITA.
>>
>> If they _really_ want that behavior anyhow, they can always just
>> completely skip defining MAKE_DEPS, as it will evaluate to an empty
>> value :).
>
> i guess we can do the conversion of the tree and then go back and evaluate if
> these _DEPS are truly necessary, and if so, how we can architect them in
> simpler terms.
Yes, because in most cases these variables aren't needed, by it helps
define prerequisite ordering (at least in my mind :\...).
Thanks,
-Garrett
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-07-18 23:28 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-12 5:42 [LTP] [PATCH 3/4] Make system enhancements, Draft 2 Garrett Cooper
2009-07-15 16:54 ` Mike Frysinger
2009-07-18 21:08 ` Garrett Cooper
2009-07-18 22:45 ` Mike Frysinger
2009-07-18 23:19 ` Garrett Cooper
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox