improved build tools
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 24 Jun 2010 07:59:42 +0000 (01:59 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 24 Jun 2010 07:59:42 +0000 (01:59 -0600)
Makefile
configure
src/Main.cc
tools/compile.lua
tools/install.lua [new file with mode: 0755]
tools/install.sh [deleted file]
tools/link.lua [new file with mode: 0755]
tools/link.sh [deleted file]

index d5718c2ca9f186a5810d8a3ea035a55f5e0d323d..5e9510c444aeb50529cbd40c399808fe896add4c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -69,22 +69,28 @@ include $(dir)/rules.mk
 #
 
 ifeq ($(DEP_TRACKING),true)
-COMPILE = ./tools/compile.lua
+COMPILE                = ./tools/compile.lua
 endif
 
+ifeq ($(AS_NEEDED),true)
+LINK           = ./tools/link.lua
+endif
+
+INSTALL                = ./tools/install.lua
+
 # Include current directory to allow sources to #include "config.h".
 CFLAGS            += -I.
 CXXFLAGS          += -I.
 
 COMMAND_CC         = $(COMPILE) $(CC)  $(CFLAGS)    $(CF_TGT) -o $@ -c $<
 COMMAND_CXX        = $(COMPILE) $(CXX) $(CXXFLAGS)  $(CF_TGT) -o $@ -c $<
-COMMAND_LD         = $(CC)  $(LDFLAGS) $(LF_TGT) -o $@ $^ $(LL_TGT) $(LIBS)
-COMMAND_LDX        = $(CXX) $(LDFLAGS) $(LF_TGT) -o $@ $^ $(LL_TGT) $(LIBS)
+COMMAND_LD         = $(LINK)    $(CC)  $(LDFLAGS)   $(LF_TGT) -o $@ $^ $(LL_TGT) $(LIBS)
+COMMAND_LDX        = $(LINK)    $(CXX) $(LDFLAGS)   $(LF_TGT) -o $@ $^ $(LL_TGT) $(LIBS)
 COMMAND_CCLD       = $(COMPILE) $(CC)  $(CFLAGS)    $(CF_TGT) $(LDFLAGS) $(LF_TGT) -o $@ $< $(LL_TGT) $(LIBS)
 COMMAND_CXXLD      = $(COMPILE) $(CXX) $(CXXFLAGS)  $(CF_TGT) $(LDFLAGS) $(LF_TGT) -o $@ $< $(LL_TGT) $(LIBS)
 COMMAND_AR         = $(AR) rcs $@ $^;  $(RANLIB)    $@
 COMMAND_RC         = $(WINDRES)        -I.          $(DF_TGT) -o $@ -i $<
-COMMAND_INSTALL    = ./tools/install.sh -m $1 $2 -d $3
+COMMAND_INSTALL    = $(INSTALL) -m $1 $2 $3/
 COMMAND_RM         = rm -f $1
 COMMAND_IN         = sed -f config.sed <"$1" >"$2"
 
index 9f97b6424af101c05f87ef3c13a75cdd932b0b01..7a4adbf4997b3d1258e56bd068ef429e011d4859 100755 (executable)
--- a/configure
+++ b/configure
@@ -51,7 +51,7 @@ Basic configuration:
       --mandir=DIR        directory to install manual pages
 
       --disable-dependency-tracking  speed up one-time builds
-      --enable-link-sh    decrease the number of direct dependencies
+      --enable-asneeded   decrease the number of direct dependencies
 
 Program options:
       --enable-debug      include debugging symbols and code paths
@@ -80,13 +80,13 @@ os.remove(config_log)
 --
 
 -- Return true if a file exists, false otherwise.
-function file_exists(file)
-       return os.execute("test -f "..file) == 0
+function file_exists(path)
+       return os.execute(string.format("test -f %q", path)) == 0
 end
 
 -- Print an error message and exit with an error.
 function die(...)
-       for _,value in ipairs(arg) do
+       for i,value in ipairs(arg) do
                print("fatal: "..tostring(value))
        end
        if file_exists(config_log) then
@@ -183,7 +183,7 @@ end
 -- code zero) given some arguments.  Returns nil if none were successful.
 function find_command(commands, args)
        if not args then args = "" end
-       for _,command in ipairs(commands) do
+       for i,command in ipairs(commands) do
                if try_run(command.." "..args) then return command end
        end
        return nil
@@ -297,7 +297,7 @@ do
                print("warning: unknown or incomplete argument "..arg)
        end
 
-       for _,arg in ipairs(arg) do
+       for i,arg in ipairs(arg) do
                parse_arg(arg)
        end
 
@@ -472,8 +472,8 @@ config.USE_HOTLOADING               = get_feature("hotloading")
 config.USE_THREADS                     = get_feature("threads")
 config.PROFILING_ENABLED       = get_feature("profile") and add_cflag("-pg")
 
-if get_feature("link-sh") then
-       -- TODO
+if get_feature("asneeded") then
+       define.AS_NEEDED = true
 end
 
 if get_package("gtk") then
index 3b05e68766601af2e367844a8771a76943442aff..9ae5156047f6205ea41d5bed190796cd7c795bb7 100644 (file)
@@ -221,35 +221,35 @@ void Main::printInfo(int argc, char* argv[])
                          << "     Compiler: " << COMPILER_STRING << std::endl
                          << "       Assets: " << assets << std::endl
                          << "Build options: "
-#ifndef HAVE_CLOCK_GETTIME
+#if !USE_CLOCK_GETTIME
                          << "-"
 #endif
                          << "clock_gettime "
-#ifdef NDEBUG
+#if !DEBUG
                          << "-"
 #endif
                          << "debug "
-#ifndef USE_DOUBLE_PRECISION
+#if !USE_DOUBLE_PRECISION
                          << "-"
 #endif
                          << "double-precision "
-#ifndef USE_GTK
+#if !USE_GTK
                          << "-"
 #endif
                          << "gtk "
-#ifndef USE_HOTLOADING
+#if !USE_HOTLOADING
                          << "-"
 #endif
                          << "hotloading "
-#ifndef PROFILING_ENABLED
+#if !PROFILING_ENABLED
                          << "-"
 #endif
                          << "profile "
-#ifndef USE_QT4
+#if !USE_QT4
                          << "-"
 #endif
                          << "qt4 "
-#ifndef USE_THREADS
+#if !USE_THREADS
                          << "-"
 #endif
                          << "threads" << std::endl
index 575096d20142da5b9832085d44e758d1575d2014..3dfff3cb9ff2a95a5c23a449dc2d502c315fe449 100755 (executable)
@@ -62,7 +62,7 @@ depfiles = {}
 table.insert(depfiles, depname)
 for path in pairs(paths) do table.insert(depfiles, path.."/"..depname) end
 
-for _,gccdep in ipairs(depfiles) do
+for i,gccdep in ipairs(depfiles) do
        tmpname = gccdep..".tmp"
        -- Fix up the dependency file with correct paths.
        if os.execute("test -f "..gccdep) == 0 and os.rename(gccdep, tmpname) then
diff --git a/tools/install.lua b/tools/install.lua
new file mode 100755 (executable)
index 0000000..89f60cd
--- /dev/null
@@ -0,0 +1,109 @@
+#!/usr/bin/env lua
+
+--
+-- Yoink
+-- This script is a predictable alternative to the system install program.
+--
+
+function show_help()
+       print([[
+
+Install files, optionally changing the mode of the installed files.
+Usage:
+  install.lua [-m MODE] SOURCE... DEST
+
+If DEST is a directory, the source(s) will be copied into DEST with their
+same names.
+]])
+end
+
+
+-- Get the next argument passed to the script.
+function shift()
+       var = arg[1]
+       table.remove(arg, 1)
+       return var
+end
+
+-- Execute a command and return its output or nil if the command failed to
+-- run.
+function backtick_run(command)
+       local fd = io.popen(command.." 2>/dev/null")
+       if fd then local stdout = fd:read("*l") fd:close() return stdout end
+       return nil
+end
+
+-- Return true if a filespec is a directory, false otherwise.
+function is_directory(path)
+       return os.execute(string.format("test -d %q", path)) == 0
+end
+
+-- Get the basename of a path.
+function basename(path, ext)
+       if not ext then ext = "" end
+       return backtick_run(string.format("basename %q %s", path, ext))
+end
+
+-- Get the directory part of a path.
+function dirname(path)
+       if path:sub(-1) == "/" then path = path .. "." end
+       return backtick_run(string.format("dirname %q", path))
+end
+
+-- Like mkdir -p except portable.
+function mkdir(path)
+       if path:sub(1,1) ~= "/" then path = os.getenv("PWD") .. "/" .. path end
+       path = path:gsub("/$", "")
+       path = path:gsub("/+", "/")
+       path = path:gsub("/[^/]+/%.%.", "")
+       path = path:gsub("%./", "")
+       path = path:gsub("/%.", "")
+
+       local compound = ""
+       for component in path:gmatch("(/[^/]*)") do
+               compound = compound .. component
+               if not is_directory(compound) then
+                       local result = os.execute(string.format("mkdir %q", compound))
+                       if result ~= 0 then os.exit(1) end
+               end
+       end
+end
+
+-- Change the mode of a file or directory.
+function chmod(mode, filespec)
+       if not mode or mode == "" then return end
+       local result = os.execute(string.format("chmod %s %q", mode, filespec))
+       if result ~= 0 then os.exit(1) end
+end
+
+-- Install a file.  If destination is a directory, the source will be
+-- installed into the directory with the same name.
+function install(mode, source, dest)
+       if is_directory(dest) then dest = dest .. "/" .. basename(source) end
+       local result = os.execute(string.format("cp %q %q", source, dest))
+       if result == 0 then chmod(mode, dest) else os.exit(1) end
+end
+
+
+files = {}
+
+-- Consume and parse each argument.
+while 0 < #arg do
+       local v = shift()
+       if v == "-h" or v == "--help" then show_help() os.exit(0) end
+       if v == "-m" then mode = shift() else table.insert(files, v) end
+end
+
+-- Check the arguments and determine the target.
+if #files < 2 then show_help() os.exit(1)
+else target = table.remove(files) end
+
+-- Perform the installation.
+if 1 < #files then
+       mkdir(target)
+       for i,file in ipairs(files) do install(mode, file, target) end
+else
+       mkdir(dirname(target))
+       install(mode, files[1], target)
+end
+
diff --git a/tools/install.sh b/tools/install.sh
deleted file mode 100755 (executable)
index 75d9598..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/bin/sh
-#
-# INSTALL (C) 2002 Emile van Bergen. Distribution of this file is allowed under
-# the conditions detailed in the GNU General Public License (GPL). See the file
-# COPYING for more information.
-#
-# This script installs zero or more files into a specified directory. If one or
-# more components of the destination path do not exist, they are created.  The
-# permissions of the destination file and the destination directory(s), if any
-# need to be created, can be specified separately. The user can also specify
-# that the operation must be skipped if the destination file or the destination
-# directory already exists. Source files are stripped of their directory
-# components before determining the destination name.
-#
-# It is intended to replace the /usr/bin/install command, which has no portable
-# subset of features that offers anything above /bin/cp. Each version is broken
-# in its own ways, the most annoying examples being that some can only install
-# a single file at a time and that some do not create destination directories
-# recursively. Hence this shell script, that is intended to be portable across
-# all POSIX-compliant /bin/sh shells. It does not assume a working 'mkdir -p'
-# command.
-#
-# Invocation:
-#
-# install arguments...
-#
-# Each argument is either an option, as specified below, a source file, or
-# a destination directory, with -d prepended. Each time a destination
-# directory is encountered, the source files leading up to it are installed,
-# and then all options are reset, allowing you to perform multiple install
-# operations with one command.
-#
-# Options:
-#
-#      -h      Show a brief usage message
-#      -v      Show what's being done
-#      -m      specify mode of destination files
-#      -md     specify mode of destination directories, if any are created
-#      -n      skip operation if destination file exists
-#      -nd     skip operation if destination directory exists
-#
-# Return values:
-#
-#      0       Successful completion
-#      >0      Error occurred
-#
-# Limitations:
-#
-# * Source files cannot start with a '-' or contain spaces
-# * Destination directories cannot start with a '-' or contain spaces
-# * If multiple different modes are desired for files in a single destination 
-#   directory, you must specify multiple installation sets (-d options), one 
-#   for each mode (eg. install -m 644 file1 file2 -d dir file3 -m 600 -d dir).
-# * The /bin/sh shell used to run this script must support user-defined 
-#   functions.
-# * The system must have mkdir, chmod, basename, tr, sed and cp available.
-#   If needed, basename and tr could be provided by sed, but I don't think
-#   that should be done by default as they are very common.
-#
-# Notes (not bugs, features. Really!):
-#
-# * If the destination directory already exists, its mode is not changed
-#   even if -md is specified; that mode is only used when creating new ones.
-# * If the destination file already exists but is overwritten because no -n
-#   was specified, the new mode, if specified, is applied as well.
-# * QNX-style paths starting with // are honored, as are .. path components.
-#   An initial .. works as expected, and a destination path a/b/../c creates
-#   a, a/b, a/c and installs the files in a/c.
-#
-# History
-#
-# 2002/09/13 - EvB - Created
-
-
-make_dir() {
-
-  dir="$1"
-  [ -n "$verbose" ] && echo "Creating directory $dir"
-
-  mkdir "$dir" || exit 1
-
-  if [ -n "$mode_dir" ] 
-  then
-    chmod "$mode_dir" "$dir" || exit 2
-  fi
-
-  return
-}
-
-
-make_dir_tree() {
-
-  root=`echo $1 | sed -e 's/[^/].*$//g'`
-  components=`echo $1 | tr / " "`
-
-  cumul=
-  for comp in $components
-  do
-    if [ -n "$cumul" ] 
-    then
-      cumul="$cumul/$comp"
-    else
-      cumul="$comp"
-    fi
-    [ "$comp" = "." ] || [ "$comp" = ".." ] || 
-      [ -d "$root$cumul" ] || make_dir "$root$cumul"
-  done
-
-  dest=$root$cumul
-}
-
-
-do_install() {
-
-  dest="$1"
-
-  if [ ! -d "$dest" ] 
-  then
-    make_dir_tree "$dest"
-  else
-    if [ -n "$new_dir" ]
-    then
-      echo "$me: Directory $dest already exists -- skipping"
-      return
-    fi
-  fi
-
-  for src_file in $src
-  do
-    file=`basename $src_file`
-    dest_file="$dest/$file"
-
-    if [ -n "$new" ] && [ -f $dest_file ]
-    then
-      echo "$me: File $dest_file already exists -- skipping"
-      continue
-    fi
-
-    [ -n "$verbose" ] && echo "Copying $src_file to $dest_file"
-    cp "$src_file" "$dest_file" || exit 3
-
-    if [ -n "$mode" ] 
-    then
-      chmod "$mode" "$dest_file" || exit 4
-    fi
-  done
-
-  return
-}
-
-
-init_opts() {
-  verbose=
-  mode=
-  mode_dir=
-  new=
-  new_dir=
-  src=
-}
-
-
-### Main entry point
-
-me=`basename $0`
-init_opts
-while [ -n "$1" ]
-do
-  case "$1" in
-
-    -v) verbose=1 ;;
-    
-    -m) mode="$2" ; shift ;;
-    -md) mode_dir="$2" ; shift ;;
-
-    -n) new=1 ;;
-    -nd) new_dir=1 ;;
-
-    -d) do_install "$2" ; init_opts ; shift ;;
-
-    -*)
-      echo Usage: $me [options] [file...] -d directory
-      exit 5
-      ;;
-
-    *) src="$src $1" ;;
-
-  esac
-  shift
-done
-
-exit 0
diff --git a/tools/link.lua b/tools/link.lua
new file mode 100755 (executable)
index 0000000..d0eed0c
--- /dev/null
@@ -0,0 +1,83 @@
+#!/usr/bin/env lua
+
+--
+-- Yoink
+-- Run this script to link the executable with fewer direct dependencies.
+--
+-- You shouldn't call this directly; instead, use the configure script's
+-- --enable-asneeded option and run make normally.  This isn't enabled by
+-- default because there is the potential for runtime linking problems on
+-- some platforms.  If you have a newer version of GCC, you should prefer
+-- the --as-needed linker flag over this method, though they both should
+-- accomplish the same thing.
+--
+
+
+-- List here any libraries that are known to not be needed on some
+-- platform.
+libraries = {
+       "atk-1.0",
+       "cairo",
+       "fontconfig",
+       "freetype",
+       "gdk-x11-2.0",
+       "gio-2.0",
+       "glib-2.0",
+       "gmodule-2.0",
+       "ogg",
+       "pango-1.0",
+       "pangocairo-1.0",
+       "pangoft2-1.0",
+       "pthread",
+       "vorbis"
+}
+
+
+-- We want to print only if verbose is set to true.
+do
+       local verbose   = os.getenv("verbose") == "true"
+       local oldprint  = print
+
+       print = function(...) if verbose then oldprint(unpack(arg)) end end
+end
+
+
+command                = arg[1]
+removed                = {}
+
+-- Get the link command as passed on the command-line.
+for i,arg in ipairs(arg) do
+       if i ~= 1 then
+               command = string.format("%s %q", command, arg)
+       end
+end
+
+original = command
+
+
+-- Check for libraries which aren't needed for successful linking.
+for i,library in ipairs(libraries) do
+       local new_command = command:gsub("%s\"%-l"..library.."+\"%s", " ")
+       if new_command ~= command then
+               if os.execute(new_command.." >/dev/null 2>&1") == 0 then
+                       print("We DON'T need "..library)
+                       table.insert(removed, library)
+                       command = new_command
+               else
+                       print("We DO need "..library)
+               end
+       end
+end
+
+
+-- Perform the final link.
+if 0 < #removed and os.execute(command.." >/dev/null 2>&1") == 0 then
+       local removed = table.concat(removed, ", ")
+       print("Linked fine without some libraries: "..removed)
+elseif os.execute(original.." >/dev/null 2>&1") == 0 then
+       print("Linked with the original link command.")
+else
+       print("The link failed.  :-(")
+       os.exit(1)
+end
+
diff --git a/tools/link.sh b/tools/link.sh
deleted file mode 100755 (executable)
index d3a739c..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/bin/sh
-
-#
-# Yoink
-# Run this script to link the executable with fewer direct dependencies.
-#
-# You shouldn't call this directly; instead, use the configure script's
-# --enable-link-sh option and run make normally.  This isn't enabled by
-# default because there is the potential for runtime linking problems on
-# some platforms.  If you have a newer version of GCC, you should prefer
-# the --as-needed linker flag over this method, though they both should
-# accomplish the same thing.
-#
-# This script was adapted from some public domain code written by Bram
-# Moolenaar for Vim.  The only input needed is the link command in the
-# variable LINK.  It is expected that the linker will return an error code
-# or this will not work.  The script caches the test results in the
-# `.link/link.sed' file; delete that file if you want to redetermine the
-# required direct dependencies.
-#
-
-
-# List here any libraries that are known to not be needed on some platform.
-libraries="\
-       atk-1.0 \
-       cairo \
-       fontconfig \
-       freetype \
-       gdk-x11-2.0 \
-       gio-2.0 \
-       glib-2.0 \
-       gmodule-2.0 \
-       ogg \
-       pango-1.0 \
-       pangocairo-1.0 \
-       pangoft2-1.0 \
-       pthread \
-       vorbis \
-       $THE_END"
-
-
-linkdir=".link"
-logfile="$linkdir/link.log"
-sedfile="$linkdir/link.sed"
-
-workdir=$(mktemp -d tmp.XXXXXXXX)
-cmdfile="$workdir/link.cmd"
-runfile="$workdir/link.run"
-
-tmpfile1="$workdir/link.tmp1"
-tmpfile2="$workdir/link.tmp2"
-tmpfile3="$workdir/link.tmp3"
-
-
-printlog()
-{
-       echo "link.sh: $@"
-}
-
-echo "$LINK " >$cmdfile
-exitcode=0
-
-
-if test -f $sedfile
-then
-       printlog "The file $sedfile exists, which is now going to be used."
-       printlog "If linking fails, try deleting the $sedfile file."
-       printlog "If that fails, try creating an empty $sedfile file."
-       printlog "If that fails, configure the package with --disable-link-sh."
-else
-       cat $cmdfile
-       if sh $cmdfile
-       then
-               mkdir -p $linkdir
-               touch $sedfile
-               cp $cmdfile $runfile
-               for libname in $libraries
-               do
-                       cont=yes
-                       while test -n "$cont"
-                       do
-                               if grep "l$libname " $runfile >/dev/null
-                               then
-                                       if test ! -f $tmpfile1
-                                       then
-                                               printlog "Full linking works; now the fun begins."
-                                               printlog "See $logfile for details."
-                                               rm -f $logfile
-                                       fi
-                                       echo "s/-l$libname  *//" >$tmpfile1
-                                       sed -f $sedfile <$cmdfile | sed -f $tmpfile1 >$runfile
-                                       # keep the last -lm; this is supposedly needed by HP-UX
-                                       if test $libname != "m" || grep "lm " $runfile >/dev/null
-                                       then
-                                               printlog "Trying to remove the $libname library..."
-                                               cat $runfile >>$logfile
-                                               if sh $runfile >>$logfile 2>&1
-                                               then
-                                                       printlog "We don't need the $libname library!"
-                                                       cat $tmpfile1 >>$sedfile
-                                                       continue
-                                               else
-                                                       printlog "We DO need the $libname library."
-                                               fi
-                                       fi
-                               fi
-                               cont=
-                               cp $cmdfile $runfile
-                       done
-               done
-               if test ! -f $tmpfile1
-               then
-                       printlog "Linked fine, no libraries can be removed."
-                       touch $tmpfile3
-               fi
-       else
-               exitcode=$?
-       fi
-fi
-
-
-if test -s $sedfile
-then
-       printlog "Using $sedfile file to remove a few libraries."
-       sed -f $sedfile <$cmdfile >$runfile
-       cat $runfile
-       if sh $runfile
-       then
-               exitcode=0
-               printlog "Linked fine with a few libraries removed."
-       else
-               exitcode=$?
-               printlog "Linking failed, making $sedfile empty and trying again."
-               mv -f $sedfile $tmpfile2
-               touch $sedfile
-       fi
-fi
-
-if test -f $sedfile -a ! -s $sedfile -a ! -f $tmpfile3
-then
-       printlog "Using unmodified link command."
-       cat $cmdfile
-       if sh $cmdfile
-       then
-               exitcode=0
-               printlog "Linked OK."
-       else
-               exitcode=$?
-               if test -f $tmpfile2
-               then
-                       printlog "Linking doesn't work at all, removing $sedfile."
-                       rm -f $sedfile
-               fi
-       fi
-fi
-
-
-rm -rf "$workdir"
-exit $exitcode
-
This page took 0.040345 seconds and 4 git commands to generate.