mirror of
https://github.com/panda3d/panda3d.git
synced 2026-02-11 01:28:58 -06:00
*** empty log message ***
This commit is contained in:
@@ -1,40 +0,0 @@
|
||||
//
|
||||
// Depends.pp
|
||||
//
|
||||
// This file is loaded and run after each Sources.pp is read. It
|
||||
// defines the inter-directory dependencies, which is useful for
|
||||
// determining build order.
|
||||
//
|
||||
|
||||
#if $[or $[eq $[DIR_TYPE], src], $[eq $[DIR_TYPE], metalib]]
|
||||
#if $[eq $[DEPENDS],]
|
||||
// Allow the user to define additional DEPENDS targets in each
|
||||
// Sources.pp.
|
||||
#define DEPENDS
|
||||
#set DEPENDS $[EXTRA_DEPENDS]
|
||||
|
||||
#forscopes metalib_target static_lib_target lib_target noinst_lib_target bin_target noinst_bin_target
|
||||
// We can optimize quite a bit by evaluating now several of the key
|
||||
// deferred variables defined in Globals.pp. This way they won't need
|
||||
// to get repeatedly reevaluated as each directory examines each
|
||||
// other.
|
||||
#define build_directory $[build_directory]
|
||||
#define build_target $[build_target]
|
||||
#define active_local_libs $[active_local_libs]
|
||||
#define active_component_libs $[active_component_libs]
|
||||
#define active_libs $[active_libs]
|
||||
#define get_sources $[get_sources]
|
||||
|
||||
// Report a warning for nonexisting dependencies.
|
||||
#define nonexisting $[unmapped all_libs,$[LOCAL_LIBS]]
|
||||
#if $[ne $[nonexisting],]
|
||||
Warning: Lib(s) $[nonexisting], referenced in $[DIRNAME]/$[TARGET], not found.
|
||||
#endif
|
||||
|
||||
#set DEPENDS $[DEPENDS] $[all_libs $[DIRNAME],$[LOCAL_LIBS] $[COMPONENT_LIBS]] $[LOCAL_INCS]
|
||||
#end metalib_target static_lib_target lib_target noinst_lib_target bin_target noinst_bin_target
|
||||
|
||||
#set DEPENDS $[sort $[DEPENDS]]
|
||||
#endif
|
||||
|
||||
#endif // DIR_TYPE
|
||||
@@ -1,167 +0,0 @@
|
||||
//
|
||||
// Global.stopgap.pp
|
||||
//
|
||||
// This file is read in before any of the individual Sources.pp files
|
||||
// are read. It defines a few global variables to assist
|
||||
// Template.stopgap.pp.
|
||||
//
|
||||
|
||||
// This subroutine fills sources, alt_cflags, alt_ipath, alt_lpath,
|
||||
// alt_libs, and alt_ld as appropriate for the current target.
|
||||
#define sources
|
||||
#define alt_cflags
|
||||
#define alt_ipath
|
||||
#define alt_lpath
|
||||
#define alt_libs
|
||||
#define alt_ld
|
||||
#defsub get_sources
|
||||
#set sources $[get_sources]
|
||||
#set alt_cflags $[get_cflags]
|
||||
#set alt_ipath $[get_ipath]
|
||||
#set alt_lpath $[get_lpath]
|
||||
#set alt_libs $[get_libs]
|
||||
#set alt_ld $[get_ld]
|
||||
#end get_sources
|
||||
|
||||
// This subroutine will set when_defer, when_no_defer, and when_either
|
||||
// correctly to the set of libs we should link with for the current
|
||||
// target.
|
||||
#define when_defer
|
||||
#define when_no_defer
|
||||
#define when_either
|
||||
#defsub get_libs
|
||||
// For the WHEN_DEFER case, we need to know the complete set of
|
||||
// metalibs that encapsulates each of our LOCAL_LIBS. In the case
|
||||
// where a particular library is not part of a metalib, we include the
|
||||
// library itself.
|
||||
|
||||
#set when_defer
|
||||
#foreach lib $[LOCAL_LIBS]
|
||||
// Only consider libraries that we're actually building.
|
||||
#if $[all_libs $[build_directory],$[lib]]
|
||||
#define modmeta $[module $[TARGET],$[lib]]
|
||||
#if $[ne $[modmeta],]
|
||||
#set when_defer $[when_defer] $[modmeta]
|
||||
#else
|
||||
#set when_defer $[when_defer] $[lib]
|
||||
#endif
|
||||
#endif
|
||||
#end lib
|
||||
#set when_defer $[unique $[when_defer]] $[patsubst %:m,%,$[filter %:m,$[OTHER_LIBS]]]
|
||||
|
||||
// Also filter out the libraries we don't want from when_no_defer, although
|
||||
// we don't need to translate these to metalibs.
|
||||
#set when_no_defer
|
||||
#foreach lib $[COMPONENT_LIBS] $[LOCAL_LIBS]
|
||||
#if $[all_libs $[build_directory],$[lib]]
|
||||
#set when_no_defer $[when_no_defer] $[lib]
|
||||
#endif
|
||||
#end lib
|
||||
#set when_no_defer $[unique $[when_no_defer]] $[patsubst %:c,%,$[filter %:c,$[OTHER_LIBS]]]
|
||||
|
||||
// Finally, get the set of libraries that we want in either case. At
|
||||
// the moment, this is just the set of libraries in OTHER_LIBS that's
|
||||
// not flagged with either a :c or a :m.
|
||||
#set when_either $[filter-out %:m %:c,$[OTHER_LIBS]]
|
||||
#end get_libs
|
||||
|
||||
|
||||
// This subroutine converts depend_libs from a list of plain library names
|
||||
// to a list of the form libname.so or libname.a, according to whether the
|
||||
// named libraries are static or dynamic.
|
||||
#defsub convert_depend_libs
|
||||
#define new_depend_libs
|
||||
#foreach lib $[depend_libs]
|
||||
// Make sure the library is something we're actually building.
|
||||
#if $[all_libs $[build_directory],$[lib]]
|
||||
#define libname $[static_libs lib$[TARGET].a,$[lib]] $[dynamic_libs lib$[TARGET].so,$[lib]]
|
||||
#if $[eq $[libname],]
|
||||
Warning: No such library $[lib], dependency of $[DIRNAME].
|
||||
#else
|
||||
#set new_depend_libs $[new_depend_libs] $[libname]
|
||||
#endif
|
||||
#endif
|
||||
#end lib
|
||||
#set depend_libs $[sort $[new_depend_libs]]
|
||||
#end convert_depend_libs
|
||||
|
||||
|
||||
// This subroutine determines the set of libraries our various targets
|
||||
// depend on. This is a complicated definition. It is the union of
|
||||
// all of our targets' dependencies, except:
|
||||
|
||||
// If a target is part of a metalib, it depends (a) directly on all of
|
||||
// its normal library dependencies that are part of the same metalib,
|
||||
// and (b) indirectly on all of the metalibs that every other library
|
||||
// dependency is part of. If a target is not part of a metalib, it is
|
||||
// the same as case (b) above.
|
||||
#define depend_libs
|
||||
#defsub get_depend_libs
|
||||
#set depend_libs
|
||||
#forscopes lib_target noinst_lib_target
|
||||
#define metalib $[module $[TARGET],$[TARGET]]
|
||||
#if $[ne $[metalib],]
|
||||
// This library is included on a metalib.
|
||||
#foreach depend $[LOCAL_LIBS]
|
||||
#define depend_metalib $[module $[TARGET],$[depend]]
|
||||
#if $[eq $[depend_metalib],$[metalib]]
|
||||
// Here's a dependent library in the *same* metalib.
|
||||
#set depend_libs $[depend_libs] $[depend]
|
||||
#elif $[ne $[depend_metalib],]
|
||||
// This dependent library is in a *different* metalib.
|
||||
#set depend_libs $[depend_libs] $[depend_metalib]
|
||||
#else
|
||||
// This dependent library is not in any metalib.
|
||||
#set depend_libs $[depend_libs] $[depend]
|
||||
#endif
|
||||
#end depend
|
||||
#else
|
||||
// This library is *not* included on a metalib.
|
||||
#foreach depend $[LOCAL_LIBS]
|
||||
#define depend_metalib $[module $[TARGET],$[depend]]
|
||||
#if $[ne $[depend_metalib],]
|
||||
// This dependent library is on a metalib.
|
||||
#set depend_libs $[depend_libs] $[depend_metalib]
|
||||
#else
|
||||
// This dependent library is not in any metalib.
|
||||
#set depend_libs $[depend_libs] $[depend]
|
||||
#endif
|
||||
#end depend
|
||||
#endif
|
||||
#end lib_target noinst_lib_target
|
||||
|
||||
// These will never be part of a metalib.
|
||||
#forscopes static_lib_target bin_target noinst_bin_target metalib_target
|
||||
#foreach depend $[LOCAL_LIBS]
|
||||
#define depend_metalib $[module $[TARGET],$[depend]]
|
||||
#if $[ne $[depend_metalib],]
|
||||
// This dependent library is on a metalib.
|
||||
#set depend_libs $[depend_libs] $[depend_metalib]
|
||||
#else
|
||||
// This dependent library is not in any metalib.
|
||||
#set depend_libs $[depend_libs] $[depend]
|
||||
#endif
|
||||
#end depend
|
||||
#end static_lib_target bin_target noinst_bin_target metalib_target
|
||||
|
||||
// In case we're defining any metalibs, these depend directly on
|
||||
// their components as well.
|
||||
#set depend_libs $[depend_libs] $[COMPONENT_LIBS(metalib_target)]
|
||||
|
||||
// Now correct all the libraries listed in depend_libs to refer to a
|
||||
// real library name.
|
||||
#define new_depend_libs
|
||||
#foreach lib $[sort $[depend_libs]]
|
||||
// Make sure the library is something we're actually building.
|
||||
#if $[all_libs $[build_directory],$[lib]]
|
||||
#define libname $[static_libs lib$[TARGET].a,$[lib]] $[dynamic_libs lib$[TARGET].so,$[lib]]
|
||||
#if $[eq $[libname],]
|
||||
Warning: No such library $[lib], dependency of $[DIRNAME].
|
||||
#else
|
||||
#set new_depend_libs $[new_depend_libs] $[libname]
|
||||
#endif
|
||||
#endif
|
||||
#end lib
|
||||
#set depend_libs $[sort $[new_depend_libs]]
|
||||
|
||||
#end get_depend_libs
|
||||
@@ -1,22 +1,15 @@
|
||||
bin_PROGRAMS = ppremake
|
||||
|
||||
ppremake_SOURCES = \
|
||||
find_searchpath.cxx find_searchpath.h \
|
||||
check_include.cxx check_include.h find_searchpath.cxx \
|
||||
find_searchpath.h \
|
||||
gnu_getopt.c gnu_getopt.h \
|
||||
ppCommandFile.cxx ppCommandFile.h ppDirectoryTree.cxx \
|
||||
ppDirectoryTree.h ppMain.cxx ppMain.h \
|
||||
ppCommandFile.cxx ppCommandFile.h ppDependableFile.cxx \
|
||||
ppDependableFile.h ppDirectory.cxx \
|
||||
ppDirectory.h ppDirectoryTree.cxx ppDirectoryTree.h \
|
||||
ppMain.cxx ppMain.h \
|
||||
ppFilenamePattern.cxx \
|
||||
ppFilenamePattern.h ppNamedScopes.cxx ppNamedScopes.h \
|
||||
ppScope.cxx ppScope.h ppSubroutine.cxx ppSubroutine.h \
|
||||
ppremake.cxx ppremake.h tokenize.cxx \
|
||||
tokenize.h
|
||||
|
||||
data_DATA = \
|
||||
System.pp Depends.pp Global.pp Template.autoconf.pp \
|
||||
Global.stopgap.pp Template.stopgap.pp \
|
||||
Global.unix.pp Template.unix.pp
|
||||
|
||||
EXTRA_DIST =\
|
||||
System.pp Depends.pp Global.pp Template.autoconf.pp \
|
||||
Global.stopgap.pp Template.stopgap.pp \
|
||||
Global.unix.pp Template.unix.pp
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
//
|
||||
// System.pp
|
||||
//
|
||||
// This is a system-wide configure file for ppremake. It's normally
|
||||
// #included from a package-specific Config.pp in the root of the
|
||||
// source tree. It makes variable declarations that are not normally
|
||||
// user-editable, but are required to set up the normal processing of
|
||||
// ppremake.
|
||||
//
|
||||
|
||||
|
||||
// Define DIR_TYPE as "src", since that's the most common kind of source
|
||||
// file.
|
||||
#if $[eq $[DIR_TYPE],]
|
||||
#define DIR_TYPE src
|
||||
#endif
|
||||
|
||||
// Define where to look for the various kinds of system files.
|
||||
#if $[eq $[DEPENDS_FILE],]
|
||||
#define DEPENDS_FILE $[PPREMAKE_DIR]/Depends.pp
|
||||
#endif
|
||||
|
||||
#if $[eq $[GLOBAL_FILE],]
|
||||
#define GLOBAL_FILE $[PPREMAKE_DIR]/Global.pp
|
||||
#endif
|
||||
|
||||
#if $[eq $[GLOBAL_TYPE_FILE],]
|
||||
#define GLOBAL_TYPE_FILE $[PPREMAKE_DIR]/Global.$[BUILD_TYPE].pp
|
||||
#endif
|
||||
|
||||
#if $[eq $[TEMPLATE_FILE],]
|
||||
#define TEMPLATE_FILE $[PPREMAKE_DIR]/Template.$[BUILD_TYPE].pp
|
||||
#endif
|
||||
@@ -1,922 +0,0 @@
|
||||
//
|
||||
// Template.autoconf.pp
|
||||
//
|
||||
// This file defines the set of output files that will be generated to
|
||||
// support an autoconf/automake style build. This works particularly
|
||||
// well when gcc/g++ will be used to compile, for instance on Linux.
|
||||
//
|
||||
|
||||
#defer get_sys_libs $[subst -ldl,@libdl@,$[patsubst %,-l%,$[UNIX_SYS_LIBS]]]
|
||||
|
||||
// First, check to see if the entire directory has been switched out.
|
||||
#define omit
|
||||
#if $[DIRECTORY_IF_GL]
|
||||
#set omit $[not $[HAVE_GL]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_GLX]
|
||||
#set omit $[not $[HAVE_GLX]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_WGL]
|
||||
#set omit $[not $[HAVE_WGL]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_GLUT]
|
||||
#set omit $[not $[HAVE_GLUT]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_SGIGL]
|
||||
#set omit $[not $[HAVE_SGIGL]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_DX]
|
||||
#set omit $[not $[HAVE_DX]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_PS2]
|
||||
#set omit $[not $[HAVE_PS2]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_RIB]
|
||||
#set omit $[not $[HAVE_RIB]]
|
||||
#endif
|
||||
#if $[DIRECTORY_IF_VRPN]
|
||||
#set omit $[not $[HAVE_VRPN]]
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if $[eq $[DIR_TYPE], src]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For a source directory, build a Makefile.am with a number of targets.
|
||||
|
||||
#output Makefile.am
|
||||
#format makefile
|
||||
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
|
||||
#if $[omit]
|
||||
// If we're omitting the directory, everything becomes an extra_dist.
|
||||
EXTRA_DIST = Sources.pp $[EXTRA_DIST] $[SOURCES(static_lib_target noinst_lib_target lib_target noinst_bin_target bin_target test_bin_target)]
|
||||
|
||||
#else // $[omit]
|
||||
|
||||
// We define a map variable that allows us to look up all the libs in
|
||||
// the various directories by target name. With this map variable, we
|
||||
// can translate the list of local_libs (which is simply a list of
|
||||
// library names, with no directory information), into a list of
|
||||
// relative filenames to each library.
|
||||
#map local_libs TARGET(*/static_lib_target */lib_target */noinst_lib_target)
|
||||
|
||||
#define all_include_dirs
|
||||
|
||||
lib_LTLIBRARIES = $[TARGET(static_lib_target lib_target):%=lib%.la]
|
||||
noinst_LTLIBRARIES = $[TARGET(noinst_lib_target):%=lib%.la]
|
||||
bin_PROGRAMS = $[TARGET(bin_target)]
|
||||
noinst_PROGRAMS = $[TARGET(noinst_bin_target)]
|
||||
EXTRA_PROGRAMS = $[TARGET(test_bin_target)]
|
||||
|
||||
#if $[ne $[YACC_PREFIX],]
|
||||
YFLAGS = -d --name-prefix=$[YACC_PREFIX] $[YFLAGS]
|
||||
LFLAGS = -P$[YACC_PREFIX] -olex.yy.c $[LFLAGS]
|
||||
#else
|
||||
YFLAGS = -d $[YFLAGS]
|
||||
LFLAGS = $[LFLAGS]
|
||||
#endif
|
||||
|
||||
#define alt_cflags @nspr_cflags@ @python_cflags@
|
||||
#define alt_lflags @nspr_lflags@
|
||||
#define alt_libs @nspr_libs@
|
||||
#if $[ne $[USE_ZLIB],]
|
||||
#define alt_cflags $[alt_cflags] @zlib_cflags@
|
||||
#define alt_lflags $[alt_lflags] @zlib_lflags@
|
||||
#define alt_libs $[alt_libs] @zlib_libs@
|
||||
#endif
|
||||
#if $[ne $[USE_GL],]
|
||||
#define alt_cflags $[alt_cflags] @gl_cflags@ @glut_cflags@
|
||||
#define alt_lflags $[alt_lflags] @gl_lflags@ @glut_lflags@
|
||||
#define alt_libs $[alt_libs] @gl_libs@ @glut_libs@
|
||||
#endif
|
||||
|
||||
#define built_sources
|
||||
#define install_data
|
||||
|
||||
#forscopes static_lib_target lib_target noinst_lib_target
|
||||
|
||||
// This map variable lets us identify which metalib, if any, is
|
||||
// including this particular library.
|
||||
#map module LOCAL_LIBS(*/metalib_target)
|
||||
|
||||
// And this defines the complete set of libs we depend on: the
|
||||
// LOCAL_LIBS we listed as directly depending on, plus all of the
|
||||
// LOCAL_LIBS *those* libraries listed, and so on.
|
||||
#define complete_local_libs $[closure local_libs,$[LOCAL_LIBS]]
|
||||
|
||||
|
||||
#if $[ne $[IF_ZLIB_SOURCES],]
|
||||
if HAVE_ZLIB
|
||||
EXTRA_ZLIB = $[IF_ZLIB_SOURCES]
|
||||
else
|
||||
EXTRA_ZLIB =
|
||||
endif
|
||||
#define SOURCES $[SOURCES] $(EXTRA_ZLIB)
|
||||
#endif
|
||||
|
||||
#define local_incs $[local_libs $[RELDIR],$[complete_local_libs]] $[RELDIR($[LOCAL_INCS:%=%/])]
|
||||
|
||||
// Check for interrogate.
|
||||
#if $[eq $[IGATESCAN], all]
|
||||
#define IGATESCAN $[filter-out %.I %.lxx %.yxx %.N,$[SOURCES]]
|
||||
#endif
|
||||
#if $[ne $[IGATESCAN],]
|
||||
#define IGATEFILE $[TARGET].in.cxx
|
||||
#define IGATEDBFILE lib$[TARGET].in
|
||||
|
||||
#define IGATELIBRARY lib$[TARGET]
|
||||
#define IGATEMODULE lib$[module $[TARGET],$[TARGET]]
|
||||
#if $[eq $[IGATEMODULE], lib]
|
||||
#define IGATEMODULE $[IGATELIBRARY]
|
||||
#endif
|
||||
|
||||
IGATESCAN = $[IGATESCAN]
|
||||
$[IGATEFILE] : $(IGATESCAN)
|
||||
@dtool@/bin/interrogate $[IGATEFLAGS] @system_igate@ -DCPPPARSER -D__cplusplus -I@dtool@/include/parser-inc @trees_inc@ $[local_incs:%=-I%] $[alt_cflags] $[CDEFINES] -module "$[IGATEMODULE]" -library "$[IGATELIBRARY]" -oc $[IGATEFILE] -od $[IGATEDBFILE] -fnames -string -refcount -assert -promiscuous -python $(IGATESCAN)
|
||||
#set built_sources $[built_sources] $[IGATEFILE]
|
||||
#set install_data $[install_data] $[IGATEDBFILE]
|
||||
#endif
|
||||
|
||||
#define SOURCES $[SOURCES] $[IGATEFILE]
|
||||
|
||||
lib$[TARGET]_la_SOURCES = $[SOURCES]
|
||||
lib$[TARGET]_la_LIBADD = $[OTHER_LIBS:%=-l%] $[alt_libs] $[get_sys_libs]
|
||||
|
||||
#set all_include_dirs $[all_include_dirs] $[local_incs]
|
||||
|
||||
|
||||
|
||||
#end static_lib_target lib_target noinst_lib_target
|
||||
|
||||
#forscopes bin_target noinst_bin_target test_bin_target
|
||||
#if $[ne $[IF_ZLIB_SOURCES],]
|
||||
if HAVE_ZLIB
|
||||
EXTRA_ZLIB = $[IF_ZLIB_SOURCES]
|
||||
else
|
||||
EXTRA_ZLIB =
|
||||
endif
|
||||
#define $[SOURCES] $(EXTRA_ZLIB)
|
||||
#endif
|
||||
|
||||
// This defines the complete set of libs we depend on: the LOCAL_LIBS
|
||||
// we listed as directly depending on, plus all of the LOCAL_LIBS
|
||||
// *those* libraries listed, and so on.
|
||||
#define complete_local_libs $[closure local_libs,$[LOCAL_LIBS]]
|
||||
|
||||
$[TARGET]_SOURCES = $[SOURCES]
|
||||
$[TARGET]_LDADD = $[local_libs $[RELDIR]/lib$[TARGET].la,$[complete_local_libs]] $[OTHER_LIBS:%=-l%] $[alt_libs] $[get_sys_libs]
|
||||
#set all_include_dirs $[all_include_dirs] $[local_libs $[RELDIR],$[complete_local_libs]]
|
||||
#set all_include_dirs $[all_include_dirs] $[RELDIR($[LOCAL_INCS:%=%/])]
|
||||
|
||||
#end bin_target noinst_bin_target test_bin_target
|
||||
|
||||
include_HEADERS = $[sort $[INSTALL_HEADERS(static_lib_target lib_target bin_target)] $[INSTALL_HEADERS]]
|
||||
#set install_data $[install_data] $[INSTALL_DATA]
|
||||
|
||||
#if $[ne $[INSTALL_PARSER_INC],]
|
||||
parserincdir = @includedir@/parser-inc
|
||||
parserinc_HEADERS = $[INSTALL_PARSER_INC]
|
||||
#endif
|
||||
|
||||
INCLUDES = $[patsubst %,-I%,$[sort $[all_include_dirs]]] @trees_inc@ $[alt_cflags]
|
||||
LDFLAGS = @ldflags@ @trees_lflags@ $[alt_lflags]
|
||||
EXTRA_DIST = Sources.pp $[EXTRA_DIST] $[INSTALL_LIBS] $[INSTALL_SCRIPTS]$[install_data]
|
||||
BUILT_SOURCES =$[built_sources]
|
||||
data_DATA =$[install_data]
|
||||
|
||||
#endif // $[omit]
|
||||
|
||||
#end Makefile.am
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#elif $[eq $[DIR_TYPE], metalib]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// A metalib directory is similar to a regular source directory,
|
||||
// but a little simpler.
|
||||
|
||||
#output Makefile.am
|
||||
#format makefile
|
||||
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
|
||||
#if $[omit]
|
||||
// If we're omitting the directory, everything becomes an extra_dist.
|
||||
EXTRA_DIST = Sources.pp $[EXTRA_DIST] $[SOURCES(static_lib_target noinst_lib_target lib_target noinst_bin_target bin_target test_bin_target)]
|
||||
|
||||
#else // $[omit]
|
||||
|
||||
// We define a map variable that allows us to look up all the libs in
|
||||
// the various directories by target name. With this map variable, we
|
||||
// can translate the list of local_libs (which is simply a list of
|
||||
// library names, with no directory information), into a list of
|
||||
// relative filenames to each library.
|
||||
#map local_libs TARGET(*/static_lib_target */lib_target */noinst_lib_target)
|
||||
|
||||
#define all_include_dirs $(includedir)
|
||||
|
||||
lib_LTLIBRARIES = $[TARGET(metalib_target):%=lib%.la]
|
||||
|
||||
#define alt_cflags @nspr_cflags@ @python_cflags@
|
||||
#define alt_lflags @nspr_lflags@
|
||||
#define alt_libs @nspr_libs@
|
||||
#if $[ne $[USE_ZLIB],]
|
||||
#define alt_cflags $[alt_cflags] @zlib_cflags@
|
||||
#define alt_lflags $[alt_lflags] @zlib_lflags@
|
||||
#define alt_libs $[alt_libs] @zlib_libs@
|
||||
#endif
|
||||
#if $[ne $[USE_GL],]
|
||||
#define alt_cflags $[alt_cflags] @gl_cflags@
|
||||
#define alt_lflags $[alt_lflags] @gl_lflags@
|
||||
#define alt_libs $[alt_libs] @gl_libs@
|
||||
#endif
|
||||
|
||||
#forscopes metalib_target
|
||||
#if $[ne $[IF_PYTHON_SOURCES],]
|
||||
if HAVE_PYTHON
|
||||
EXTRA_PYTHON = $[IF_PYTHON_SOURCES]
|
||||
else
|
||||
EXTRA_PYTHON =
|
||||
endif
|
||||
#define SOURCES $[SOURCES] $(EXTRA_PYTHON)
|
||||
#endif
|
||||
|
||||
// This defines the complete set of libs we depend on: the LOCAL_LIBS
|
||||
// we listed as directly depending on, plus all of the LOCAL_LIBS
|
||||
// *those* libraries listed, and so on.
|
||||
#define complete_local_libs $[closure local_libs,$[LOCAL_LIBS]]
|
||||
|
||||
lib$[TARGET]_la_SOURCES = $[SOURCES]
|
||||
lib$[TARGET]_la_LIBADD = $[complete_local_libs:%=-l%] $[get_sys_libs]
|
||||
|
||||
#end metalib_target
|
||||
|
||||
INCLUDES = $[patsubst %,-I%,$[sort $[all_include_dirs]]] @trees_inc@ $[alt_cflags]
|
||||
LDFLAGS = @ldflags@ -L$(libdir) -rpath $(libdir) @trees_lflags@ $[alt_lflags]
|
||||
EXTRA_DIST = Sources.pp $[EXTRA_DIST]
|
||||
|
||||
#endif // $[omit]
|
||||
|
||||
#end Makefile.am
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#elif $[eq $[DIR_TYPE], group]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#output Makefile.am
|
||||
#format makefile
|
||||
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
|
||||
SUBDIRS = $[SUBDIRS]
|
||||
|
||||
EXTRA_DIST = Sources.pp $[EXTRA_DIST]
|
||||
|
||||
#end Makefile.am
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#elif $[eq $[DIR_TYPE], toplevel]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#output Makefile.am
|
||||
#format makefile
|
||||
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
|
||||
FIRSTBUILD_SUBDIRS = $[filter_out metalibs,$[SUBDIRS]]
|
||||
SUBDIRS = $[SUBDIRS]
|
||||
|
||||
#define INSTALL_HEADERS $[INSTALL_HEADERS] $[CONFIG_HEADER]
|
||||
|
||||
include_HEADERS = $[INSTALL_HEADERS]
|
||||
|
||||
EXTRA_DIST = Sources.pp Config.pp $[EXTRA_DIST]
|
||||
|
||||
|
||||
# We define this custom rule for all-recursive as an ordering hack.
|
||||
# It's just like the default rule, except that it traverses through
|
||||
# only FIRSTBUILD_SUBDIRS, instead of all of SUBDIRS. The idea is
|
||||
# that first we build everything in FIRSTBUILD_SUBDIRS, and then when
|
||||
# we're installing, we build everything in SUBDIRS as well. This hack
|
||||
# is necessary to build targets in metalibs that link directly with
|
||||
# installed shared libraries.
|
||||
|
||||
all-recursive:
|
||||
@set fnord $(MAKEFLAGS); amf=$$2; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(FIRSTBUILD_SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
#end Makefile.am
|
||||
|
||||
#output configure.in
|
||||
#format straight
|
||||
dnl configure.in generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT($[SAMPLE_SOURCE_FILE])
|
||||
AM_INIT_AUTOMAKE($[PACKAGE], $[VERSION])
|
||||
|
||||
#if $[eq $[CONFIG_HEADER],]
|
||||
dnl This package doesn't care about a generated config.h file. This causes
|
||||
dnl a few problems with automake, so we fake it out with this hack.
|
||||
AM_CONFIG_HEADER(ignore_config.h)
|
||||
#else
|
||||
AM_CONFIG_HEADER($[CONFIG_HEADER])
|
||||
#endif
|
||||
|
||||
if test "${CTPROJS+set}" = set; then
|
||||
if test "${$[upcase $[PACKAGE]]+set}" != set; then
|
||||
echo ""
|
||||
echo "The environment variable CTPROJS is currently set, indicating"
|
||||
echo "you are attached to one or more trees, but you are not attached"
|
||||
echo "to $[upcase $[PACKAGE]]. Either unattach from everything, or attach to $[upcase $[PACKAGE]]."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If we're currently attached, the install directory is the same as
|
||||
# the source directory.
|
||||
if test "$prefix" != "NONE"; then
|
||||
echo ""
|
||||
echo The environment variable CTPROJS is currently set, indicating
|
||||
echo you are attached to one or more trees. When you configure the
|
||||
echo package while attached, you cannot specify a --prefix to install
|
||||
echo the built sources--it always installs in the source directory.
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
prefix=$$[upcase $[PACKAGE]]
|
||||
fi
|
||||
|
||||
AC_PREFIX_DEFAULT($[INSTALL_DIR])
|
||||
AC_PROG_MAKE_SET
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
# If we have a CFLAGS variable but not a CXXFLAGS variable, let them
|
||||
# be the same.
|
||||
if test "${CXXFLAGS+set}" != set -a "${CFLAGS+set}" = set; then
|
||||
CXXFLAGS=$CFLAGS
|
||||
fi
|
||||
|
||||
# Save these variables for later, so we can easily append to them or
|
||||
# change them.
|
||||
user_ldflags=${LDFLAGS-}
|
||||
user_cflags=${CFLAGS-}
|
||||
user_cxxflags=${CXXFLAGS-}
|
||||
|
||||
dnl Choose a suitable set of system-dependent interrogate flags.
|
||||
case "$host_os" in
|
||||
irix*) system_igate="-D__mips__ -D__MIPSEB__";;
|
||||
linux-gnu*) system_igate="-D__i386__";;
|
||||
esac
|
||||
AC_SUBST(system_igate)
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AM_PROG_LEX
|
||||
AM_DISABLE_STATIC
|
||||
AM_PROG_LIBTOOL
|
||||
AC_PATH_XTRA
|
||||
|
||||
dnl We require specifically Bison, not any other flavor of Yacc.
|
||||
AC_CHECK_PROGS(YACC, 'bison -y')
|
||||
|
||||
|
||||
AC_ARG_WITH(optimize,
|
||||
[ --with-optimize=LEVEL Specify the optimization/debug symbol level (1-4, default 1)])
|
||||
|
||||
if test "${with_optimize-no}" = "no"; then
|
||||
with_optimize=$[OPTIMIZE]
|
||||
fi
|
||||
|
||||
if test "$with_optimize" = "1"; then
|
||||
# Optimize level 1: No optimizations, and full debug symbols.
|
||||
if test "${ac_cv_prog_gcc}" = "yes"; then
|
||||
CFLAGS="$user_cflags -g -Wall"
|
||||
CXXFLAGS="$user_cxxflags -g -Wall"
|
||||
else
|
||||
CFLAGS="$user_cflags -g"
|
||||
CXXFLAGS="$user_cxxflags -g"
|
||||
fi
|
||||
|
||||
elif test "$with_optimize" = "2"; then
|
||||
# Optimize level 2: Compiler optimizations, and full debug if supported.
|
||||
if test "${ac_cv_prog_gcc}" = "yes"; then
|
||||
CFLAGS="$user_cflags -O2 -g -Wall"
|
||||
CXXFLAGS="$user_cxxflags -O2 -g -Wall"
|
||||
else
|
||||
CFLAGS="$user_cflags -O"
|
||||
CXXFLAGS="$user_cxxflags -O"
|
||||
fi
|
||||
|
||||
elif test "$with_optimize" = "3"; then
|
||||
# Optimize level 3: Compiler optimizations, without debug symbols.
|
||||
if test "${ac_cv_prog_gcc}" = "yes"; then
|
||||
CFLAGS="$user_cflags -O2 -Wall"
|
||||
CXXFLAGS="$user_cxxflags -O2 -Wall"
|
||||
else
|
||||
CFLAGS="$user_cflags -O"
|
||||
CXXFLAGS="$user_cxxflags -O"
|
||||
fi
|
||||
|
||||
elif test "$with_optimize" = "4"; then
|
||||
# Optimize level 4: As above, with asserts removed.
|
||||
if test "${ac_cv_prog_gcc}" = "yes"; then
|
||||
CFLAGS="$user_cflags -O2 -Wall -DNDEBUG"
|
||||
CXXFLAGS="$user_cxxflags -O2 -Wall -DNDEBUG"
|
||||
else
|
||||
CFLAGS="$user_cflags -O -DNDEBUG"
|
||||
CXXFLAGS="$user_cxxflags -O -DNDEBUG"
|
||||
fi
|
||||
|
||||
else
|
||||
echo "Invalid optimize level: $with_optimize"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
trees_inc=
|
||||
trees_lflags=
|
||||
|
||||
#foreach require $[REQUIRED_TREES]
|
||||
|
||||
AC_ARG_WITH($[require],
|
||||
[ --with-$[require]=DIR Prefix where $[upcase $[require]] is installed (same as --prefix)])
|
||||
|
||||
|
||||
if test "${CTPROJS+set}" = set; then
|
||||
if test "$with_$[require]" != ""; then
|
||||
echo ""
|
||||
echo "The environment variable CTPROJS is currently set, indicating"
|
||||
echo "you are attached to one or more trees. When you configure the"
|
||||
echo "package while attached, you cannot specify a directory to search"
|
||||
echo "for --$[require]; it will always search in the currently attached $[upcase $[require]]."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
if test "${$[upcase $[require]]+set}" != set; then
|
||||
echo ""
|
||||
echo "The environment variable CTPROJS is currently set, indicating"
|
||||
echo "you are attached to one or more trees, but you are not attached"
|
||||
echo "to $[upcase $[require]]. Either unattach from everything, or attach to $[upcase $[require]]."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$[require]='${$[upcase $[require]]}'
|
||||
else
|
||||
# No attachments--respect the --with-$[require] parameter.
|
||||
|
||||
if test "$with_$[require]" != "" -a "$with_$[require]" != "no" -a "$with_$[require]" != "yes"; then
|
||||
$[require]=$with_$[require]
|
||||
else
|
||||
$[require]='${prefix}'
|
||||
fi
|
||||
trees_inc="$trees_inc -I"'$($[require])/include'
|
||||
trees_lflags="$trees_lflags -L"'$($[require])/lib'
|
||||
fi
|
||||
|
||||
AC_SUBST($[require])
|
||||
|
||||
#end require
|
||||
AC_SUBST(trees_inc)
|
||||
AC_SUBST(trees_lflags)
|
||||
|
||||
dnl First, we'll test for C-specific features.
|
||||
AC_LANG_C
|
||||
|
||||
dnl Checks for libraries.
|
||||
libdl=
|
||||
libm=
|
||||
AC_CHECK_LIB(dl, dlopen, libdl=-ldl)
|
||||
AC_CHECK_LIB(m, sin, libm=-lm)
|
||||
AC_SUBST(libdl)
|
||||
AC_SUBST(libm)
|
||||
|
||||
// Only bother to make the following tests if we're actually building
|
||||
// a config.h.
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(malloc.h alloca.h unistd.h io.h minmax.h sys/types.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_BIGENDIAN
|
||||
AC_GETTIMEOFDAY
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(getopt getopt_long_only)
|
||||
|
||||
|
||||
dnl Now we can test some C++-specific features.
|
||||
AC_LANG_CPLUSPLUS
|
||||
AC_HEADER_IOSTREAM
|
||||
AC_CHECK_HEADERS(sstream)
|
||||
AC_NAMESPACE
|
||||
AC_IOS_BINARY
|
||||
#endif
|
||||
|
||||
AC_LANG_C
|
||||
|
||||
AC_ARG_WITH(python,
|
||||
[ --with-python=DIR Prefix where Python is installed (usually /usr/local)])
|
||||
|
||||
have_python=no
|
||||
include_python=
|
||||
if test "$with_python" != "no"; then
|
||||
if test "$with_python" = "yes" -o "$with_python" = ""; then
|
||||
AC_SEARCH_HPACKAGE(/usr/local /usr,
|
||||
python1.6 python,
|
||||
Python.h, python)
|
||||
else
|
||||
AC_SEARCH_HPACKAGE($with_python,
|
||||
python1.6 python,
|
||||
Python.h, python)
|
||||
fi
|
||||
|
||||
if test "$with_python" != ""; then
|
||||
if test "$python_PKG" != "yes"; then
|
||||
dnl If the user specified to search for python but we didn't find it,
|
||||
dnl abort now.
|
||||
|
||||
echo ""
|
||||
echo "**** Could not locate Python package. Use --with-python=directory,"
|
||||
echo " e.g. --with-python=/usr/local, or just --with-python."
|
||||
echo " If Python is not installed, specify --without-python."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$python_PKG" = "yes"; then
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_PYTHON)
|
||||
#endif
|
||||
have_python=yes
|
||||
python_cflags=-I$python_INCLUDE
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(have_python)
|
||||
AC_SUBST(python_cflags)
|
||||
AM_CONDITIONAL(HAVE_PYTHON, test "$have_python" = "yes")
|
||||
|
||||
|
||||
AC_ARG_WITH(nspr,
|
||||
[ --with-nspr=DIR Prefix where NSPR is installed (usually /usr/local/mozilla)])
|
||||
|
||||
have_nspr=no
|
||||
include_nspr=
|
||||
if test "$with_nspr" != "no"; then
|
||||
if test "$with_nspr" = "yes" -o "$with_nspr" = ""; then
|
||||
AC_SEARCH_PACKAGE(/usr/local/mozilla /usr/local/mozilla/dist/*,,
|
||||
nspr.h, nspr3, PR_Init, nspr)
|
||||
else
|
||||
AC_SEARCH_PACKAGE($with_nspr $with_nspr/dist/*,,
|
||||
nspr.h, nspr3, PR_Init, nspr)
|
||||
fi
|
||||
|
||||
if test "$with_nspr" != ""; then
|
||||
if test "$nspr_PKG" != "yes"; then
|
||||
dnl If the user specified to search for NSPR but we didn't find it,
|
||||
dnl abort now.
|
||||
|
||||
echo ""
|
||||
echo "**** Could not locate NSPR package. Use --with-nspr=directory,"
|
||||
echo " e.g. --with-nspr=/usr/local, or just --with-nspr."
|
||||
echo " If NSPR is not installed, specify --without-nspr."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$nspr_PKG" = "yes"; then
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_NSPR)
|
||||
#endif
|
||||
have_nspr=yes
|
||||
nspr_cflags="-I$nspr_INCLUDE"
|
||||
nspr_ldflags="-L$nspr_LIB"
|
||||
nspr_libs="-lnspr3"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(have_nspr)
|
||||
AC_SUBST(nspr_cflags)
|
||||
AC_SUBST(nspr_lflags)
|
||||
AC_SUBST(nspr_libs)
|
||||
AM_CONDITIONAL(HAVE_NSPR, test "$have_nspr" = "yes")
|
||||
|
||||
|
||||
AC_ARG_WITH(zlib,
|
||||
[ --with-zlib=DIR Prefix where zlib is installed (usually /usr)])
|
||||
|
||||
have_zlib=no
|
||||
include_zlib=
|
||||
if test "$with_zlib" != "no"; then
|
||||
if test "$with_zlib" = "yes" -o "$with_zlib" = ""; then
|
||||
AC_SEARCH_PACKAGE(/usr /usr/local,,
|
||||
zlib.h, z, gzopen, zlib)
|
||||
else
|
||||
AC_SEARCH_PACKAGE($with_zlib,,
|
||||
zlib.h, z, gzopen, zlib)
|
||||
fi
|
||||
|
||||
if test "$with_zlib" != ""; then
|
||||
if test "$zlib_PKG" != "yes"; then
|
||||
dnl If the user specified to search for zlib but we didn't find it,
|
||||
dnl abort now.
|
||||
|
||||
echo ""
|
||||
echo "**** Could not locate zlib package. Use --with-zlib=directory,"
|
||||
echo " e.g. --with-zlib=/usr/local, or just --with-zlib."
|
||||
echo " If zlib is not installed, specify --without-zlib."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$zlib_PKG" = "yes"; then
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_ZLIB)
|
||||
#endif
|
||||
have_zlib=yes
|
||||
if test "$zlib_INCLUDE" != ""; then
|
||||
zlib_cflags="-I$zlib_INCLUDE"
|
||||
fi
|
||||
if test "$zlib_LIB" != ""; then
|
||||
zlib_lflags="-L$zlib_LIB"
|
||||
fi
|
||||
zlib_libs="-lz"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(have_zlib)
|
||||
AC_SUBST(zlib_cflags)
|
||||
AC_SUBST(zlib_lflags)
|
||||
AC_SUBST(zlib_libs)
|
||||
AM_CONDITIONAL(HAVE_ZLIB, test "$have_zlib" = "yes")
|
||||
|
||||
|
||||
AC_ARG_WITH(gl,
|
||||
[ --with-gl=DIR Prefix where OpenGL is installed (usually /usr)])
|
||||
|
||||
have_gl=no
|
||||
include_gl=
|
||||
if test "$with_gl" != "no"; then
|
||||
if test "$with_gl" = "yes" -o "$with_gl" = ""; then
|
||||
AC_SEARCH_PACKAGE(/usr /usr/local,,
|
||||
GL/gl.h, GL, glVertex3f, gl)
|
||||
else
|
||||
AC_SEARCH_PACKAGE($with_gl,,
|
||||
GL/gl.h, GL, glVertex3f, gl)
|
||||
fi
|
||||
|
||||
if test "$with_gl" != ""; then
|
||||
if test "$gl_PKG" != "yes"; then
|
||||
dnl If the user specified to search for OpenGL but we didn't find it,
|
||||
dnl abort now.
|
||||
|
||||
echo ""
|
||||
echo "**** Could not locate OpenGL package. Use --with-gl=directory,"
|
||||
echo " e.g. --with-gl=/usr/local, or just --with-gl."
|
||||
echo " If OpenGL is not installed, specify --without-gl."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$gl_PKG" = "yes"; then
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_GL)
|
||||
#endif
|
||||
have_gl=yes
|
||||
if test "$gl_INCLUDE" != ""; then
|
||||
gl_cflags="-I$gl_INCLUDE"
|
||||
fi
|
||||
if test "$gl_LIB" != ""; then
|
||||
gl_lflags="-L$gl_LIB"
|
||||
fi
|
||||
gl_libs="-lGL -lGLU"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(have_gl)
|
||||
AC_SUBST(gl_cflags)
|
||||
AC_SUBST(gl_lflags)
|
||||
AC_SUBST(gl_libs)
|
||||
AM_CONDITIONAL(HAVE_GL, test "$have_gl" = "yes")
|
||||
|
||||
|
||||
AC_ARG_WITH(glu,
|
||||
[ --with-glu=DIR Prefix where GL util library is installed (usually /usr)])
|
||||
|
||||
have_glu=no
|
||||
include_glu=
|
||||
if test "$with_glu" != "no"; then
|
||||
if test "$with_glu" = "yes" -o "$with_glu" = ""; then
|
||||
AC_SEARCH_PACKAGE($gl_INCLUDE /usr /usr/local,,
|
||||
GL/glu.h, GLU, gluSphere, glu)
|
||||
else
|
||||
AC_SEARCH_PACKAGE($with_glu,,
|
||||
GL/glu.h, GLU, gluSphere, glu)
|
||||
fi
|
||||
|
||||
if test "$with_glu" != ""; then
|
||||
if test "$glu_PKG" != "yes"; then
|
||||
dnl If the user specified to search for GL util library but we didn't find it,
|
||||
dnl abort now.
|
||||
|
||||
echo ""
|
||||
echo "**** Could not locate GL util library. Use --with-glu=directory,"
|
||||
echo " e.g. --with-glu=/usr/local, or just --with-glu."
|
||||
echo " If GL util library is not installed, specify --without-glu."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$glu_PKG" = "yes"; then
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_GLU)
|
||||
#endif
|
||||
have_glu=yes
|
||||
if test "$glu_INCLUDE" != ""; then
|
||||
glu_cflags="-I$glu_INCLUDE"
|
||||
fi
|
||||
if test "$glu_LIB" != ""; then
|
||||
glu_lflags="-L$glu_LIB"
|
||||
fi
|
||||
glu_libs="-lGLU -lGLUU"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(have_glu)
|
||||
AC_SUBST(glu_cflags)
|
||||
AC_SUBST(glu_lflags)
|
||||
AC_SUBST(glu_libs)
|
||||
AM_CONDITIONAL(HAVE_GLU, test "$have_glu" = "yes")
|
||||
|
||||
|
||||
AC_ARG_WITH(glx,
|
||||
[ --with-glx=DIR Prefix where GLX is installed (usually /usr)])
|
||||
|
||||
have_glx=no
|
||||
include_glx=
|
||||
if test "$with_glx" != "no"; then
|
||||
if test "$with_glx" = "yes" -o "$with_glx" = ""; then
|
||||
AC_SEARCH_HPACKAGE($gl_INCLUDE /usr /usr/local $x_libraries,,
|
||||
GL/glx.h, glx)
|
||||
else
|
||||
AC_SEARCH_HPACKAGE($with_glx,,
|
||||
GL/glx.h, glx)
|
||||
fi
|
||||
|
||||
if test "$with_glx" != ""; then
|
||||
if test "$glx_PKG" != "yes"; then
|
||||
dnl If the user specified to search for GLX but we didn't find it,
|
||||
dnl abort now.
|
||||
|
||||
echo ""
|
||||
echo "**** Could not locate GLX package. Use --with-glx=directory,"
|
||||
echo " e.g. --with-glx=/usr/local, or just --with-glx."
|
||||
echo " If GLX is not installed, specify --without-glx."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$glx_PKG" = "yes"; then
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_GLX)
|
||||
#endif
|
||||
have_glx=yes
|
||||
if test "$glx_INCLUDE" != ""; then
|
||||
glx_cflags="-I$glx_INCLUDE"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(have_glx)
|
||||
AC_SUBST(glx_cflags)
|
||||
AM_CONDITIONAL(HAVE_GLX, test "$have_glx" = "yes")
|
||||
|
||||
|
||||
AC_ARG_WITH(glut,
|
||||
[ --with-glut=DIR Prefix where glut is installed (usually /usr)])
|
||||
|
||||
have_glut=no
|
||||
include_glut=
|
||||
if test "$with_glut" != "no"; then
|
||||
if test "$with_glut" = "yes" -o "$with_glut" = ""; then
|
||||
AC_SEARCH_PACKAGE($gl_INCLUDE /usr /usr/local $x_libraries,,
|
||||
GL/glut.h, glut, glutInit, glut, -lGL -lGLU)
|
||||
else
|
||||
AC_SEARCH_PACKAGE($with_glut,,
|
||||
GLUT/glut.h, glut, glutInit, glut, -lGL -lGLU)
|
||||
fi
|
||||
|
||||
if test "$with_glut" != ""; then
|
||||
if test "$glut_PKG" != "yes"; then
|
||||
dnl If the user specified to search for glut but we didn't find it,
|
||||
dnl abort now.
|
||||
|
||||
echo ""
|
||||
echo "**** Could not locate glut package. Use --with-glut=directory,"
|
||||
echo " e.g. --with-glut=/usr/local, or just --with-glut."
|
||||
echo " If glut is not installed, specify --without-glut."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$glut_PKG" = "yes"; then
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_GLUT)
|
||||
#endif
|
||||
have_glut=yes
|
||||
if test "$glut_INCLUDE" != ""; then
|
||||
glut_cflags="-I$glut_INCLUDE"
|
||||
fi
|
||||
if test "$glut_LIB" != ""; then
|
||||
glut_lflags="-L$glut_LIB"
|
||||
fi
|
||||
glut_libs="-lglut"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(have_glut)
|
||||
AC_SUBST(glut_cflags)
|
||||
AC_SUBST(glut_lflags)
|
||||
AC_SUBST(glut_libs)
|
||||
AM_CONDITIONAL(HAVE_GLUT, test "$have_glut" = "yes")
|
||||
|
||||
|
||||
AC_ARG_WITH(rib,
|
||||
[ --with-rib Compile in the Renderman interface.])
|
||||
|
||||
have_rib=no
|
||||
if test "$with_rib" = "yes"; then
|
||||
have_rib=yes
|
||||
fi
|
||||
|
||||
AC_SUBST(have_rib)
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
if test "$have_rib" = "yes"; then
|
||||
AC_DEFINE(HAVE_RIB)
|
||||
fi
|
||||
#endif
|
||||
AM_CONDITIONAL(HAVE_RIB, test "$have_rib" = "yes")
|
||||
|
||||
|
||||
|
||||
AC_ARG_WITH(mikmod,
|
||||
[ --with-mikmod[=libmikmod-config] Use the mikmod interface for audio.])
|
||||
|
||||
have_mikmod=no
|
||||
include_mikmod=
|
||||
if test "$with_mikmod" != "no"; then
|
||||
if test "$with_mikmod" = "" -o "$with_mikmod" = "yes"; then
|
||||
dnl search for the libmikmod-config program on the path.
|
||||
AC_CHECK_PROG(with_mikmod, libmikmod-config, libmikmod-config, "no")
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$with_mikmod" != "no"; then
|
||||
have_mikmod=yes
|
||||
CFLAGS="$CFLAGS "`$with_mikmod --cflags`
|
||||
CXXFLAGS="$CXXFLAGS "`$with_mikmod --cflags`
|
||||
LDFLAGS="$LDFLAGS "`$with_mikmod --libs`
|
||||
#if $[ne $[CONFIG_HEADER],]
|
||||
AC_DEFINE(HAVE_MIKMOD)
|
||||
#endif
|
||||
fi
|
||||
|
||||
AC_SUBST(have_mikmod)
|
||||
AM_CONDITIONAL(HAVE_MIKMOD, test "$have_mikmod" = "yes")
|
||||
|
||||
ldflags=$LDFLAGS
|
||||
AC_SUBST(ldflags)
|
||||
|
||||
AC_OUTPUT([$[TREE:%=%/Makefile]])
|
||||
|
||||
#end configure.in
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#endif // DIR_TYPE
|
||||
@@ -1,711 +0,0 @@
|
||||
//
|
||||
// Template.stopgap.pp
|
||||
//
|
||||
// This file defines the set of output files that will be generated to
|
||||
// support our old-style Makefile system. It is intended to aid as a
|
||||
// transition to the new system.
|
||||
//
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if $[eq $[DIR_TYPE], src]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For a source directory, build a Makefile, Makefile.install, and a
|
||||
// Makefile.target for each target.
|
||||
|
||||
#define submakes $[TARGET(static_lib_target):%=%.a] $[TARGET(lib_target noinst_lib_target):%=%.so] $[TARGET(sed_bin_target bin_target noinst_bin_target test_bin_target)]
|
||||
#define install $[TARGET(static_lib_target):%=%.a] $[TARGET(lib_target noinst_lib_target):%=%.so] $[TARGET(sed_bin_target bin_target noinst_bin_target)]
|
||||
|
||||
// Now iterate through the libraries we're building and see which ones
|
||||
// actually *are* being included in a metalib. For each one that is,
|
||||
// we install the appropriate deferred file.
|
||||
#define deferred
|
||||
#forscopes lib_target
|
||||
#define metalib $[module $[TARGET],$[TARGET]]
|
||||
#if $[ne $[metalib],]
|
||||
#set deferred $[deferred] Deferred.$[metalib].lib$[TARGET].so
|
||||
#endif
|
||||
#end lib_target
|
||||
|
||||
// Get the full set of libraries we depend on.
|
||||
#call get_depend_libs
|
||||
|
||||
// Also get the targets we'll be installing.
|
||||
#define install_libs $[sort $[TARGET(lib_target):%=lib%.so] $[TARGET(static_lib_target):%=lib%.a] $[INSTALL_LIBS]]
|
||||
#define install_bin $[sort $[TARGET(bin_target)] $[INSTALL_BIN]]
|
||||
#define install_scripts $[sort $[INSTALL_SCRIPTS(static_lib_target lib_target bin_target)] $[TARGET(sed_bin_target)] $[INSTALL_SCRIPTS]]
|
||||
#define install_headers $[sort $[INSTALL_HEADERS(static_lib_target lib_target bin_target)] $[INSTALL_HEADERS]]
|
||||
#define install_data $[sort $[INSTALL_DATA(static_lib_target lib_target sed_bin_target bin_target)] $[INSTALL_DATA]] $[sort $[INSTALL_CONFIG(static_lib_target lib_target sed_bin_target bin_target)] $[INSTALL_CONFIG]]
|
||||
|
||||
// Collect the set of interrogate database files we'll install,
|
||||
// possibly one for each library we build.
|
||||
#define install_igatedb
|
||||
#if $[HAVE_PYTHON]
|
||||
#forscopes lib_target
|
||||
#if $[ne $[IGATESCAN],]
|
||||
#set install_igatedb $[install_igatedb] lib$[TARGET].in
|
||||
#endif
|
||||
#end lib_target
|
||||
#endif
|
||||
|
||||
|
||||
#output Makefile
|
||||
#format makefile
|
||||
#### Meta Makefile.
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
|
||||
#### Sub make targets (extension of sub Makefile, eg 'foo' for Makefile.foo):
|
||||
SUBMAKES = $[submakes]
|
||||
|
||||
#### List the minimal set of sub makes on the list above required to install.
|
||||
INSTALL = $[install]
|
||||
|
||||
#### Location of sub Makefiles.
|
||||
MAKEDIR = .
|
||||
|
||||
#### The action is here.
|
||||
include $(DTOOL)/include/Makefile.meta.rules
|
||||
|
||||
#### Sub-make build order dependencies:
|
||||
# foo: bar
|
||||
#end Makefile
|
||||
|
||||
|
||||
|
||||
#output Makefile.install
|
||||
#format makefile
|
||||
#### Installation makefile
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
# Note: This file is included by the project-wide Makefile so the current
|
||||
# directory is the project root. Also, commented-out fields are optional.
|
||||
|
||||
#### Package name and location (if not src/all/$(PACKAGE)):
|
||||
PACKAGE = $[DIRNAME]
|
||||
PKGROOT = $[PATH]
|
||||
|
||||
ifneq (,$(PACKAGE))
|
||||
|
||||
#### Package dependencies (USESOTHER needs relative paths from project root):
|
||||
USESLIBS = $[depend_libs]
|
||||
# USESINCLUDE =
|
||||
# USESOTHER =
|
||||
|
||||
#### Installed files:
|
||||
LIBS = $[install_libs]
|
||||
DEFERRED = $[deferred]
|
||||
INCLUDE = $[install_headers]
|
||||
BINS = $[install_bin]
|
||||
SCRIPTS = $[install_scripts]
|
||||
# SS =
|
||||
# STK =
|
||||
# MODELS =
|
||||
ETC = $[install_data]
|
||||
IGATEDB =$[install_igatedb]
|
||||
# DOC =
|
||||
# MAN =
|
||||
# FONTS =
|
||||
# ICONS =
|
||||
# APPDEFAULTS =
|
||||
# TCL =
|
||||
# TELEUSE =
|
||||
# SHADERS =
|
||||
|
||||
#### Other files to be installed (use relative pathname from project root):
|
||||
#if $[ne $[INSTALL_PARSER_INC],]
|
||||
PARSER_INC = $[INSTALL_PARSER_INC]
|
||||
SRC_PARSER_INC = $(addprefix $(PKGROOT)/,$(PARSER_INC))
|
||||
INST_PARSER_INC = $(addprefix include/parser-inc/,$(PARSER_INC))
|
||||
OTHER = $(INST_PARSER_INC)
|
||||
#else
|
||||
# OTHER =
|
||||
#endif
|
||||
|
||||
#### Where the action happens.
|
||||
include $(DTOOL)/include/Makefile.install.rules
|
||||
|
||||
#### Install actions for OTHER files (source must be in $(PKGROOT)):
|
||||
# [ installed file ] : $(PKGROOT)/[ source file ] # Files must have same name
|
||||
# $(INSTALL) # Copies from source to dest
|
||||
#
|
||||
# [ installed file ] : $(PKGROOT)/[ source file ]
|
||||
# $(MKINSTALL) # Also makes directory if needed
|
||||
|
||||
#if $[ne $[INSTALL_PARSER_INC],]
|
||||
$(INST_PARSER_INC) : include/parser-inc/% : $(PKGROOT)/%
|
||||
$(MKINSTALL)
|
||||
#endif
|
||||
|
||||
#### Other install/uninstall actions:
|
||||
# install-$(PKGROOT): #Add dependencies here
|
||||
# Add actions here
|
||||
#
|
||||
# uninstall-$(PKGROOT): #Add dependencies here
|
||||
# Add actions here
|
||||
|
||||
#### Sub-package Makefile.install inclusions:
|
||||
# include foo/Makefile.install
|
||||
|
||||
endif
|
||||
#end Makefile.install
|
||||
|
||||
|
||||
|
||||
// Now generate a suitable Makefile for each library target.
|
||||
#forscopes lib_target noinst_lib_target
|
||||
|
||||
// Again, is this library included in a metalib? If so, output the
|
||||
// appropriate deferred rules.
|
||||
#define metalib $[module $[TARGET],$[TARGET]]
|
||||
|
||||
// We might need to define a BUILDING_ symbol for win32. We use the
|
||||
// BUILDING_DLL variable name, defined typically in the metalib, for
|
||||
// this; but in some cases, where the library isn't part of a metalib,
|
||||
// we define BUILDING_DLL directly for the target.
|
||||
#define building_var $[BUILDING_DLL]
|
||||
#if $[ne $[metalib],]
|
||||
#set building_var $[module $[BUILDING_DLL],$[TARGET]]
|
||||
#endif
|
||||
|
||||
// Get the full set of sources for this target.
|
||||
#call get_sources
|
||||
#call get_libs
|
||||
|
||||
// Which files will we interrogate, if any?
|
||||
#if $[HAVE_PYTHON]
|
||||
#if $[ne $[IGATESCAN],]
|
||||
#if $[eq $[IGATESCAN],all]
|
||||
#define igatescan $[filter-out %.I %.lxx %.yxx %.N,$[sources]]
|
||||
#else
|
||||
#define igatescan $[IGATESCAN]
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#output Makefile.$[TARGET].so
|
||||
#format makefile
|
||||
#### Makefile for DSO's. Any fields commented out are optional.
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
#### Target's name:
|
||||
TARGET = lib$[TARGET].so
|
||||
DEFERRED_TARGET = $[metalib]
|
||||
|
||||
# Standard .o file conversion information.
|
||||
|
||||
#### Lex files
|
||||
LFILES = $[filter %.lxx,$[sources]]
|
||||
LEX = flex
|
||||
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
|
||||
LEXTENSION = cxx
|
||||
|
||||
#### Yacc files
|
||||
YFILES = $[filter %.yxx,$[sources]]
|
||||
YACC = bison
|
||||
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
|
||||
YEXTENSION = cxx
|
||||
|
||||
#### C files
|
||||
CFILES = $[filter %.c,$[sources]]
|
||||
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
|
||||
|
||||
#### C++ files
|
||||
C++FILES = $[filter %.cxx,$[sources]]
|
||||
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
|
||||
# USETEMPLATES = TRUE
|
||||
# PTREPOSITORY = # Specify only if you want a specific name
|
||||
|
||||
#### Interrogate info
|
||||
IGATESCAN = $[igatescan]
|
||||
IGATEFLAGS = $[alt_ipath:%=-I%]
|
||||
# IGATEFILE = # Specify only if you want a specific name
|
||||
|
||||
#### Additional search directories for C/C++ header files:
|
||||
IPATH = $[alt_ipath:%=-I%]
|
||||
|
||||
#### Location to put .o files:
|
||||
# ODIR =
|
||||
|
||||
#### Source file dependencies (unnecessary with clearmake)
|
||||
# foo.c: foo.h
|
||||
|
||||
#### Other files and lib. Include $(ODIR) in any .o names.
|
||||
# OFILES =
|
||||
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
|
||||
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
|
||||
LIBS = $[when_either:%=-l%]
|
||||
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
|
||||
|
||||
#### Additional search directories for lib:
|
||||
LPATH = $[alt_lpath:%=-L%]
|
||||
|
||||
#### Other linker flags.
|
||||
#if $[ne $[alt_ld],]
|
||||
LD = $[alt_ld]
|
||||
#endif
|
||||
# LDFLAGS =
|
||||
|
||||
#### Pull in standard .o make variables
|
||||
include $(DTOOL)/include/Makefile.o.vars
|
||||
|
||||
#### The .o action is here.
|
||||
include $(DTOOL)/include/Makefile.o.rules
|
||||
|
||||
#### Pull in standard binary make variables.
|
||||
include $(DTOOL)/include/Makefile.bin.vars
|
||||
|
||||
#### The .so action is here.
|
||||
include $(DTOOL)/include/Makefile.so.rules
|
||||
#end Makefile.$[TARGET].so
|
||||
|
||||
#end lib_target noinst_lib_target
|
||||
|
||||
|
||||
|
||||
// Also generate a suitable Makefile for each static library target.
|
||||
#forscopes static_lib_target
|
||||
|
||||
// Get the full set of sources for this target.
|
||||
#call get_sources
|
||||
#call get_libs
|
||||
|
||||
#output Makefile.$[TARGET].a
|
||||
#format makefile
|
||||
#### Makefile for archive libraries. Any fields commented out are optional.
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
#### Target's name:
|
||||
TARGET = lib$[TARGET].a
|
||||
|
||||
# Standard .o file conversion information.
|
||||
|
||||
#### Lex files
|
||||
LFILES = $[filter %.lxx,$[sources]]
|
||||
LEX = flex
|
||||
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
|
||||
LEXTENSION = yy.cxx
|
||||
# LSUBST =
|
||||
|
||||
#### Yacc files
|
||||
YFILES = $[filter %.yxx,$[sources]]
|
||||
YACC = bison
|
||||
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
|
||||
YEXTENSION = tab.cxx
|
||||
# YSUBST =
|
||||
|
||||
#### C files
|
||||
CFILES = $[filter %.c,$[sources]]
|
||||
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
|
||||
|
||||
#### C++ files
|
||||
C++FILES = $[filter %.cxx,$[sources]]
|
||||
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
|
||||
# USETEMPLATES = TRUE
|
||||
# PTREPOSITORY = # Specify only if you want a specific name
|
||||
|
||||
#### Additional search directories for C/C++ header files:
|
||||
IPATH = $[alt_ipath:%=-I%]
|
||||
|
||||
#### Location to put .o files:
|
||||
# ODIR =
|
||||
|
||||
#### Source file dependencies (unnecessary with clearmake)
|
||||
# foo.c: foo.h
|
||||
|
||||
#### Other .o files.
|
||||
# OFILES =
|
||||
|
||||
#### Libs and flags for template instantiation.
|
||||
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
|
||||
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
|
||||
LIBS = $[when_either:%=-l%]
|
||||
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
|
||||
|
||||
#### Additional search directories for lib:
|
||||
LPATH = $[alt_lpath:%=-L%]
|
||||
|
||||
#### Archiver flags
|
||||
# ARFLAGS =
|
||||
|
||||
#### Pull in standard .o make variables
|
||||
include $(DTOOL)/include/Makefile.o.vars
|
||||
|
||||
#### The .o action is here.
|
||||
include $(DTOOL)/include/Makefile.o.rules
|
||||
|
||||
#### Pull in standard binary make variables.
|
||||
include $(DTOOL)/include/Makefile.bin.vars
|
||||
|
||||
#### The .a action is here.
|
||||
include $(DTOOL)/include/Makefile.a.rules
|
||||
#end Makefile.$[TARGET].a
|
||||
|
||||
#end static_lib_target
|
||||
|
||||
|
||||
|
||||
// And also generate a suitable Makefile for each binary target.
|
||||
#forscopes bin_target noinst_bin_target test_bin_target
|
||||
|
||||
// Get the full set of sources for this target.
|
||||
#call get_sources
|
||||
#call get_libs
|
||||
|
||||
#output Makefile.$[TARGET]
|
||||
#format makefile
|
||||
#### Makefile for binaries. Any fields commented out are optional.
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
#### Target's name:
|
||||
TARGET = $[TARGET]
|
||||
|
||||
# Standard .o file conversion information.
|
||||
|
||||
#### Lex files
|
||||
LFILES = $[filter %.lxx,$[sources]]
|
||||
LEX = flex
|
||||
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
|
||||
LEXTENSION = yy.cxx
|
||||
# LSUBST =
|
||||
|
||||
#### Yacc files
|
||||
YFILES = $[filter %.yxx,$[sources]]
|
||||
YACC = bison
|
||||
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
|
||||
YEXTENSION = tab.cxx
|
||||
# YSUBST =
|
||||
|
||||
#### C files
|
||||
CFILES = $[filter %.c,$[sources]]
|
||||
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
|
||||
|
||||
#### C++ files
|
||||
C++FILES = $[filter %.cxx,$[sources]]
|
||||
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
|
||||
|
||||
#### Additional search directories for C/C++ header files:
|
||||
IPATH = $[alt_ipath:%=-I%]
|
||||
|
||||
#### Location to put .o files:
|
||||
# ODIR =
|
||||
|
||||
#### Source file dependencies (unnecessary with clearmake)
|
||||
# foo.c: foo.h
|
||||
|
||||
#### Other files and lib. Include $(ODIR) in any .o names.
|
||||
# OFILES =
|
||||
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
|
||||
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
|
||||
LIBS = $[when_either:%=-l%]
|
||||
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
|
||||
|
||||
#### Additional search directories for lib:
|
||||
LPATH = $[alt_lpath:%=-L%]
|
||||
|
||||
#### Other linker flags.
|
||||
#if $[ne $[alt_ld],]
|
||||
LD = $[alt_ld]
|
||||
#endif
|
||||
# LDFLAGS =
|
||||
|
||||
#### Pull in standard .o make variables
|
||||
include $(DTOOL)/include/Makefile.o.vars
|
||||
|
||||
#### The .o action is here.
|
||||
include $(DTOOL)/include/Makefile.o.rules
|
||||
|
||||
#### Pull in standard binary make variables.
|
||||
include $(DTOOL)/include/Makefile.bin.vars
|
||||
|
||||
#### The bin action is here.
|
||||
include $(DTOOL)/include/Makefile.bin.rules
|
||||
#end Makefile.$[TARGET]
|
||||
|
||||
#end bin_target noinst_bin_target test_bin_target
|
||||
|
||||
|
||||
// Finally, generate the special scripts from the sed_bin_targets. Hopefully
|
||||
// there won't be too many of these in the tree, since these are fairly
|
||||
// Unix-specific.
|
||||
#forscopes sed_bin_target
|
||||
#output Makefile.$[TARGET]
|
||||
#format makefile
|
||||
#### This is a special makefile just to generate the $[TARGET] script.
|
||||
|
||||
$[TARGET] : $[SOURCE]
|
||||
sed $[COMMAND] $^ >$@
|
||||
chmod +x $@
|
||||
|
||||
clean :
|
||||
|
||||
cleanall :
|
||||
rm -f $[TARGET]
|
||||
#end Makefile.$[TARGET]
|
||||
#end sed_bin_target
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#elif $[eq $[DIR_TYPE], metalib]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// A metalib directory is similar to a regular source directory,
|
||||
// but a little simpler.
|
||||
|
||||
#define submakes $[TARGET(metalib_target):%=%.so]
|
||||
|
||||
|
||||
// Get the full set of libraries we depend on.
|
||||
#call get_depend_libs
|
||||
|
||||
// Also get the targets we'll be installing.
|
||||
#define install_libs $[TARGET(metalib_target):%=lib%.so]
|
||||
#define install_headers $[INSTALL_HEADERS(metalib_target)]
|
||||
#define install_data $[INSTALL_DATA(metalib_target)] $[INSTALL_CONFIG(metalib_target)]
|
||||
|
||||
|
||||
#output Makefile
|
||||
#format makefile
|
||||
#### Meta Makefile.
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
|
||||
#### Sub make targets (extension of sub Makefile, eg 'foo' for Makefile.foo):
|
||||
SUBMAKES = $[submakes]
|
||||
|
||||
#### List the minimal set of sub makes on the list above required to install.
|
||||
INSTALL = $[submakes]
|
||||
|
||||
#### Location of sub Makefiles.
|
||||
MAKEDIR = .
|
||||
|
||||
#### The action is here.
|
||||
include $(DTOOL)/include/Makefile.meta.rules
|
||||
|
||||
#### Sub-make build order dependencies:
|
||||
# foo: bar
|
||||
#end Makefile
|
||||
|
||||
|
||||
|
||||
#output Makefile.install
|
||||
#format makefile
|
||||
#### Installation makefile
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
# Note: This file is included by the project-wide Makefile so the current
|
||||
# directory is the project root. Also, commented-out fields are optional.
|
||||
|
||||
#### Package name and location (if not src/all/$(PACKAGE)):
|
||||
PACKAGE = $[DIRNAME]
|
||||
PKGROOT = $[PATH]
|
||||
|
||||
ifneq (,$(PACKAGE))
|
||||
|
||||
#### Package dependencies (USESOTHER needs relative paths from project root):
|
||||
USESLIBS = $[depend_libs]
|
||||
# USESINCLUDE =
|
||||
# USESOTHER =
|
||||
|
||||
#### Installed files:
|
||||
LIBS = $[install_libs]
|
||||
INCLUDE = $[install_headers]
|
||||
# BINS =
|
||||
# SS =
|
||||
# STK =
|
||||
# MODELS =
|
||||
# ETC =
|
||||
# DOC =
|
||||
# MAN =
|
||||
# FONTS =
|
||||
# ICONS =
|
||||
# APPDEFAULTS =
|
||||
# TCL =
|
||||
# TELEUSE =
|
||||
# SHADERS =
|
||||
|
||||
#### Other files to be installed (use relative pathname from project root):
|
||||
# OTHER =
|
||||
|
||||
#### Where the action happens.
|
||||
include $(DTOOL)/include/Makefile.install.rules
|
||||
|
||||
#### Install actions for OTHER files (source must be in $(PKGROOT)):
|
||||
# [ installed file ] : $(PKGROOT)/[ source file ] # Files must have same name
|
||||
# $(INSTALL) # Copies from source to dest
|
||||
#
|
||||
# [ installed file ] : $(PKGROOT)/[ source file ]
|
||||
# $(MKINSTALL) # Also makes directory if needed
|
||||
|
||||
#### Other install/uninstall actions:
|
||||
# install-$(PKGROOT): #Add dependencies here
|
||||
# Add actions here
|
||||
#
|
||||
# uninstall-$(PKGROOT): #Add dependencies here
|
||||
# Add actions here
|
||||
|
||||
#### Sub-package Makefile.install inclusions:
|
||||
# include foo/Makefile.install
|
||||
|
||||
endif
|
||||
#end Makefile.install
|
||||
|
||||
// Now generate a suitable Makefile for each metalib target.
|
||||
#forscopes metalib_target
|
||||
|
||||
#define building_var $[BUILDING_DLL]
|
||||
|
||||
// Get the full set of sources for this target.
|
||||
#call get_sources
|
||||
#call get_libs
|
||||
|
||||
#if $[HAVE_PYTHON]
|
||||
#if $[ne $[components $[IGATESCAN],$[COMPONENT_LIBS]],]
|
||||
#define igatemscan $[TARGET]
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#output Makefile.$[TARGET].so
|
||||
#format makefile
|
||||
#### Makefile for DSO's. Any fields commented out are optional.
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
#### Target's name:
|
||||
TARGET = lib$[TARGET].so
|
||||
|
||||
# Standard .o file conversion information.
|
||||
|
||||
#### Lex files
|
||||
LFILES = $[filter %.lxx,$[sources]]
|
||||
LEX = flex
|
||||
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
|
||||
LEXTENSION = yy.cxx
|
||||
# LSUBST =
|
||||
|
||||
#### Yacc files
|
||||
YFILES = $[filter %.yxx,$[sources]]
|
||||
YACC = bison
|
||||
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
|
||||
YEXTENSION = tab.cxx
|
||||
# YSUBST =
|
||||
|
||||
#### C files
|
||||
CFILES = $[filter %.c,$[sources]]
|
||||
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
|
||||
|
||||
#### C++ files
|
||||
C++FILES = $[filter %.cxx,$[sources]]
|
||||
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
|
||||
# USETEMPLATES = TRUE
|
||||
# PTREPOSITORY = # Specify only if you want a specific name
|
||||
|
||||
#### Interrogate info
|
||||
# IGATESCAN =
|
||||
# IGATEFLAGS =
|
||||
# IGATEFILE = # Specify only if you want a specific name
|
||||
IGATEMSCAN = $[igatemscan]
|
||||
|
||||
#### Pull in deferred-target files built in other packages
|
||||
DEFERRED_FILES = $[TARGET]
|
||||
|
||||
#### Additional search directories for C/C++ header files:
|
||||
IPATH = $[alt_ipath:%=-I%]
|
||||
|
||||
#### Location to put .o files:
|
||||
# ODIR =
|
||||
|
||||
#### Source file dependencies (unnecessary with clearmake)
|
||||
# foo.c: foo.h
|
||||
|
||||
#### Other files and lib. Include $(ODIR) in any .o names.
|
||||
# OFILES =
|
||||
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
|
||||
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
|
||||
LIBS = $[when_either:%=-l%]
|
||||
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
|
||||
|
||||
#### Additional search directories for lib:
|
||||
LPATH = $[alt_lpath:%=-L%]
|
||||
|
||||
#### Other linker flags.
|
||||
#if $[ne $[alt_ld],]
|
||||
LD = $[alt_ld]
|
||||
#endif
|
||||
# LDFLAGS =
|
||||
|
||||
#### Pull in standard .o make variables
|
||||
include $(DTOOL)/include/Makefile.o.vars
|
||||
|
||||
#### The .o action is here.
|
||||
include $(DTOOL)/include/Makefile.o.rules
|
||||
|
||||
#### Pull in standard binary make variables.
|
||||
include $(DTOOL)/include/Makefile.bin.vars
|
||||
|
||||
#### The .so action is here.
|
||||
include $(DTOOL)/include/Makefile.so.rules
|
||||
#end Makefile.$[TARGET].so
|
||||
|
||||
#end metalib_target
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#elif $[eq $[DIR_TYPE], group]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a group directory: a directory above a collection of source
|
||||
// directories, e.g. $DTOOL/src. We don't need to output anything in
|
||||
// this directory.
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#elif $[eq $[DIR_TYPE], toplevel]
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is the toplevel directory, e.g. $DTOOL. Here we build the
|
||||
// root makefile and also synthesize the dtool_config.h (or whichever
|
||||
// file) we need.
|
||||
|
||||
#output Makefile
|
||||
#format makefile
|
||||
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
|
||||
################################# DO NOT EDIT ###########################
|
||||
|
||||
# Specify project name and project root directory.
|
||||
CTPROJECT = $[PACKAGE]
|
||||
CTPROJROOT = $($[upcase $[PACKAGE]])
|
||||
|
||||
include $(DTOOL)/include/Makefile.project.vars
|
||||
|
||||
// Iterate through all of our known source files. Each src and
|
||||
// metalib type file gets its corresponding Makefile.install listed
|
||||
// here. However, we test for $[DIR_TYPE] of toplevel, because the
|
||||
// source directories typically don't define their own DIR_TYPE
|
||||
// variable, and they end up inheriting this one dynamically.
|
||||
#forscopes */
|
||||
#if $[or $[eq $[DIR_TYPE], src],$[eq $[DIR_TYPE], metalib],$[and $[eq $[DIR_TYPE], toplevel],$[ne $[DIRNAME],top]]]
|
||||
#if $[build_directory]
|
||||
include $[PATH]/Makefile.install
|
||||
#endif
|
||||
#endif
|
||||
#end */
|
||||
|
||||
#end Makefile
|
||||
|
||||
// If there is a file called LocalSetup.pp in the package's top
|
||||
// directory, then invoke that. It might contain some further setup
|
||||
// instructions.
|
||||
#sinclude $[TOPDIRPREFIX]LocalSetup.stopgap.pp
|
||||
#sinclude $[TOPDIRPREFIX]LocalSetup.pp
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#endif // DIR_TYPE
|
||||
64
ppremake/check_include.cxx
Normal file
64
ppremake/check_include.cxx
Normal file
@@ -0,0 +1,64 @@
|
||||
// Filename: check_include.cxx
|
||||
// Created by: drose (16Oct00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "check_include.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: check_include
|
||||
// Description: Checks to see if the given line is a C/C++ #include
|
||||
// directive. If it is, returns the named filename;
|
||||
// otherwise, returns the empty string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string
|
||||
check_include(const string &line) {
|
||||
// Skip initial whitespace on the line.
|
||||
size_t p = 0;
|
||||
while (p < line.length() && isspace(line[p])) {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (p >= line.length() || line[p] != '#') {
|
||||
// No hash mark.
|
||||
return string();
|
||||
}
|
||||
|
||||
// We have a hash mark! Skip more whitespace.
|
||||
p++;
|
||||
while (p < line.length() && isspace(line[p])) {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (p >= line.length() || !(line.substr(p, 7) == "include")) {
|
||||
// Some other directive, not #include.
|
||||
return string();
|
||||
}
|
||||
|
||||
// It's an #include directive! Skip more whitespace.
|
||||
p += 7;
|
||||
while (p < line.length() && isspace(line[p])) {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (p >= line.length() || (line[p] != '"' && line[p] != '<')) {
|
||||
cerr << "Ignoring invalid #include directive: " << line << "\n";
|
||||
return string();
|
||||
}
|
||||
|
||||
char close = (line[p] == '"') ? '"' : '>';
|
||||
|
||||
p++;
|
||||
// Now get the filename.
|
||||
size_t q = p;
|
||||
while (q < line.length() && line[q] != close) {
|
||||
q++;
|
||||
}
|
||||
|
||||
if (q >= line.length()) {
|
||||
cerr << "Ignoring invalid #include directive: " << line << "\n";
|
||||
return string();
|
||||
}
|
||||
|
||||
return line.substr(p, q - p);
|
||||
}
|
||||
14
ppremake/check_include.h
Normal file
14
ppremake/check_include.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Filename: check_include.h
|
||||
// Created by: drose (16Oct00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CHECK_INCLUDE_H
|
||||
#define CHECK_INCLUDE_H
|
||||
|
||||
#include "ppremake.h"
|
||||
|
||||
string check_include(const string &line);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(ppremake.cxx)
|
||||
AM_INIT_AUTOMAKE(ppremake, 0.26)
|
||||
AM_INIT_AUTOMAKE(ppremake, 0.50)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_PREFIX_DEFAULT(/usr/local/panda)
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h> // for tempnam()
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <utime.h>
|
||||
|
||||
static const string begin_comment(BEGIN_COMMENT);
|
||||
|
||||
@@ -823,13 +825,31 @@ handle_format_command() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPCommandFile::
|
||||
handle_output_command() {
|
||||
vector<string> words;
|
||||
tokenize_whitespace(_scope->expand_string(_params), words);
|
||||
|
||||
if (words.empty()) {
|
||||
cerr << "#output command requires one parameter.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockNesting *nest = new BlockNesting;
|
||||
nest->_state = BS_output;
|
||||
nest->_name = trim_blanks(_scope->expand_string(_params));
|
||||
nest->_name = words[0];
|
||||
nest->_write_state = _write_state;
|
||||
nest->_scope = _scope;
|
||||
nest->_next = _block_nesting;
|
||||
|
||||
// Also check the output flags.
|
||||
nest->_flags = 0;
|
||||
for (int i = 1; i < (int)words.size(); i++) {
|
||||
if (words[i] == "notouch") {
|
||||
nest->_flags |= OF_notouch;
|
||||
} else {
|
||||
cerr << "Invalid output flag: " << words[i] << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_block_nesting = nest;
|
||||
|
||||
if (!_in_for) {
|
||||
@@ -1036,7 +1056,8 @@ handle_end_command() {
|
||||
|
||||
// Verify the output file.
|
||||
if (nest->_tempnam != (char *)NULL) {
|
||||
if (!compare_output(nest->_tempnam, nest->_true_name)) {
|
||||
if (!compare_output(nest->_tempnam, nest->_true_name,
|
||||
(nest->_flags & OF_notouch) != 0)) {
|
||||
return false;
|
||||
}
|
||||
free(nest->_tempnam);
|
||||
@@ -1503,7 +1524,8 @@ replay_formap(const string &varname, const string &mapvar) {
|
||||
// same, remove the temporary file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPCommandFile::
|
||||
compare_output(const string &temp_name, const string &true_name) {
|
||||
compare_output(const string &temp_name, const string &true_name,
|
||||
bool notouch) {
|
||||
ifstream in_a(temp_name.c_str());
|
||||
ifstream in_b(true_name.c_str());
|
||||
|
||||
@@ -1538,6 +1560,15 @@ compare_output(const string &temp_name, const string &true_name) {
|
||||
if (unlink(temp_name.c_str()) < 0) {
|
||||
cerr << "Warning: unable to remove temporary file " << temp_name << "\n";
|
||||
}
|
||||
|
||||
// Even though the file is unchanged, unless the "notouch" flag is
|
||||
// set, we want to update the modification time. This helps the
|
||||
// makefiles know we did something.
|
||||
if (!notouch) {
|
||||
if (utime(true_name.c_str(), (struct utimbuf *)NULL) < 0) {
|
||||
cerr << "Warning: unable to touch " << true_name << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -67,7 +67,8 @@ protected:
|
||||
bool replay_forscopes(const string &name);
|
||||
bool replay_foreach(const string &varname, const vector<string> &words);
|
||||
bool replay_formap(const string &varname, const string &mapvar);
|
||||
bool compare_output(const string &temp_name, const string &true_name);
|
||||
bool compare_output(const string &temp_name, const string &true_name,
|
||||
bool notouch);
|
||||
bool failed_if() const;
|
||||
|
||||
bool is_valid_formal(const string &formal_parameter_name) const;
|
||||
@@ -131,6 +132,10 @@ private:
|
||||
WriteFormat _format;
|
||||
bool _last_blank;
|
||||
};
|
||||
|
||||
enum OutputFlags {
|
||||
OF_notouch = 0x001,
|
||||
};
|
||||
|
||||
class BlockNesting {
|
||||
public:
|
||||
@@ -142,6 +147,7 @@ private:
|
||||
char *_tempnam;
|
||||
ofstream _output;
|
||||
vector<string> _words;
|
||||
int _flags;
|
||||
BlockNesting *_next;
|
||||
};
|
||||
|
||||
|
||||
413
ppremake/ppDependableFile.cxx
Normal file
413
ppremake/ppDependableFile.cxx
Normal file
@@ -0,0 +1,413 @@
|
||||
// Filename: ppDependableFile.cxx
|
||||
// Created by: drose (15Oct00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ppDependableFile.h"
|
||||
#include "ppDirectory.h"
|
||||
#include "ppDirectoryTree.h"
|
||||
#include "check_include.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDependableFile::
|
||||
PPDependableFile(PPDirectory *directory, const string &filename) :
|
||||
_directory(directory),
|
||||
_filename(filename)
|
||||
{
|
||||
_flags = 0;
|
||||
_mtime = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::update_from_cache
|
||||
// Access: Public
|
||||
// Description: Called as the dependency cache file is being read,
|
||||
// this asks the file to update its information from the
|
||||
// cache file if appropriate. This means comparing the
|
||||
// cached modification time against the file's actual
|
||||
// modification time, and storing the cached
|
||||
// dependencies if they match.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDependableFile::
|
||||
update_from_cache(const vector<string> &words) {
|
||||
// Shouldn't call this once the file has actually been read.
|
||||
assert((_flags & F_updated) == 0);
|
||||
assert((_flags & F_updating) == 0);
|
||||
assert((_flags & F_from_cache) == 0);
|
||||
assert(words.size() >= 2);
|
||||
|
||||
// The second parameter is the cached modification time.
|
||||
time_t mtime = strtol(words[1].c_str(), (char **)NULL, 10);
|
||||
if (mtime == get_mtime()) {
|
||||
// The modification matches; preserve the cache information.
|
||||
PPDirectoryTree *tree = _directory->get_tree();
|
||||
|
||||
_dependencies.clear();
|
||||
vector<string>::const_iterator wi;
|
||||
for (wi = words.begin() + 2; wi != words.end(); ++wi) {
|
||||
string dirpath = (*wi);
|
||||
|
||||
Dependency dep;
|
||||
dep._okcircular = false;
|
||||
|
||||
if (dirpath.length() > 1 && dirpath[0] == '/') {
|
||||
// If the first character is '/', it means that the file has
|
||||
// been marked okcircular.
|
||||
dep._okcircular = true;
|
||||
dirpath = dirpath.substr(1);
|
||||
}
|
||||
|
||||
if (dirpath.length() > 2 && dirpath.substr(0, 2) == "*/") {
|
||||
// This is an extra include file, not a file in this source
|
||||
// tree.
|
||||
_extra_includes.push_back(dirpath.substr(2));
|
||||
|
||||
} else {
|
||||
dep._file =
|
||||
tree->get_dependable_file_by_dirpath(dirpath, false);
|
||||
if (dep._file != (PPDependableFile *)NULL) {
|
||||
_dependencies.push_back(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_flags |= F_from_cache;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::write_cache
|
||||
// Access: Public
|
||||
// Description: Writes the dependency information out as a single
|
||||
// line to the indicated dependency cache file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDependableFile::
|
||||
write_cache(ostream &out) {
|
||||
out << _filename << " " << get_mtime();
|
||||
|
||||
Dependencies::const_iterator di;
|
||||
for (di = _dependencies.begin(); di != _dependencies.end(); ++di) {
|
||||
out << " ";
|
||||
if ((*di)._okcircular) {
|
||||
out << "/";
|
||||
}
|
||||
out << (*di)._file->get_dirpath();
|
||||
}
|
||||
|
||||
// Also write out the extra includes--those #include directives
|
||||
// which do not reference a file within this source tree. We need
|
||||
// those just for comparison's sake later, so we can tell whether
|
||||
// the cache line is still current (without having to know which
|
||||
// files are part of the tree).
|
||||
ExtraIncludes::const_iterator ei;
|
||||
for (ei = _extra_includes.begin(); ei != _extra_includes.end(); ++ei) {
|
||||
out << " */" << (*ei);
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_directory
|
||||
// Access: Public
|
||||
// Description: Returns the directory that this file can be found in.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectory *PPDependableFile::
|
||||
get_directory() const {
|
||||
return _directory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_filename
|
||||
// Access: Public
|
||||
// Description: Returns the local filename of this particular file
|
||||
// within the directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &PPDependableFile::
|
||||
get_filename() const {
|
||||
return _filename;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_pathname
|
||||
// Access: Public
|
||||
// Description: Returns the relative pathname from the root of the
|
||||
// source tree to this particular filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDependableFile::
|
||||
get_pathname() const {
|
||||
return _directory->get_path() + "/" + _filename;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_dirpath
|
||||
// Access: Public
|
||||
// Description: Returns an abbreviated pathname to this file, in the
|
||||
// form dirname/filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDependableFile::
|
||||
get_dirpath() const {
|
||||
return _directory->get_dirname() + "/" + _filename;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::exists
|
||||
// Access: Public
|
||||
// Description: Returns true if the file exists, false if it does
|
||||
// not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDependableFile::
|
||||
exists() {
|
||||
stat_file();
|
||||
return ((_flags & F_exists) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_mtime
|
||||
// Access: Public
|
||||
// Description: Returns the last modification time of the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
time_t PPDependableFile::
|
||||
get_mtime() {
|
||||
stat_file();
|
||||
return _mtime;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_num_dependencies
|
||||
// Access: Public
|
||||
// Description: Returns the number of files this file depends on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPDependableFile::
|
||||
get_num_dependencies() {
|
||||
update_dependencies();
|
||||
return _dependencies.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_dependency
|
||||
// Access: Public
|
||||
// Description: Returns the nth file this file depends on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDependableFile *PPDependableFile::
|
||||
get_dependency(int n) {
|
||||
assert((_flags & F_updated) != 0);
|
||||
assert(n >= 0 && n < (int)_dependencies.size());
|
||||
return _dependencies[n]._file;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_complete_dependencies
|
||||
// Access: Public
|
||||
// Description: Recursively determines the complete set of files this
|
||||
// file depends on. It is the user's responsibility to
|
||||
// empty the set before calling this function; the
|
||||
// results will simply be added to the existing set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDependableFile::
|
||||
get_complete_dependencies(set<PPDependableFile *> &files) {
|
||||
update_dependencies();
|
||||
Dependencies::const_iterator di;
|
||||
for (di = _dependencies.begin(); di != _dependencies.end(); ++di) {
|
||||
PPDependableFile *file = (*di)._file;
|
||||
if (files.insert(file).second) {
|
||||
file->get_complete_dependencies(files);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::is_circularity
|
||||
// Access: Public
|
||||
// Description: Returns true if a circular dependency exists between
|
||||
// this file and one or more other files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDependableFile::
|
||||
is_circularity() {
|
||||
update_dependencies();
|
||||
return (_flags & F_circularity) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::get_circularity
|
||||
// Access: Public
|
||||
// Description: If is_circularity() returns true, returns a string
|
||||
// describing the circular dependency path for the user.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDependableFile::
|
||||
get_circularity() {
|
||||
update_dependencies();
|
||||
return _circularity;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::was_examined
|
||||
// Access: Public
|
||||
// Description: Returns true if anyone ever asked this file for its
|
||||
// list of dependencies, or false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDependableFile::
|
||||
was_examined() const {
|
||||
return ((_flags & F_updated) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::update_dependencies
|
||||
// Access: Private
|
||||
// Description: Builds up the dependency list--the list of files this
|
||||
// file depends on--if it hasn't already been built. If
|
||||
// a circular dependency is detected during this
|
||||
// process, _circularity and _circularity_detected will
|
||||
// be updated accordingly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDependableFile::
|
||||
update_dependencies() {
|
||||
if ((_flags & F_updated) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert((_flags & F_updating) == 0);
|
||||
string circularity;
|
||||
compute_dependencies(circularity);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::compute_dependencies
|
||||
// Access: Private
|
||||
// Description: Builds up the dependency list--the list of files this
|
||||
// file depends on--if it hasn't already been built.
|
||||
//
|
||||
// If a circularity is detected, e.g. two files depend
|
||||
// on each other, a pointer to the offending file is
|
||||
// returned and the string is updated to indicate the
|
||||
// circularity. Otherwise, if there is no circularity,
|
||||
// NULL is returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDependableFile *PPDependableFile::
|
||||
compute_dependencies(string &circularity) {
|
||||
if ((_flags & F_updated) != 0) {
|
||||
return (PPDependableFile *)NULL;
|
||||
|
||||
} else if ((_flags & F_updating) != 0) {
|
||||
// Oh oh, a circular dependency!
|
||||
circularity = get_dirpath();
|
||||
return this;
|
||||
}
|
||||
|
||||
_flags |= F_updating;
|
||||
|
||||
if ((_flags & F_from_cache) == 0) {
|
||||
// Now open the file and scan it for #include statements.
|
||||
ifstream in(get_pathname().c_str());
|
||||
if (!in) {
|
||||
// Can't read the file, or the file doesn't exist. Interesting.
|
||||
if (exists()) {
|
||||
cerr << "Warning: dependent file " << get_pathname()
|
||||
<< " exists but cannot be read.\n";
|
||||
} else {
|
||||
cerr << "Warning: dependent file " << get_pathname()
|
||||
<< " does not exist.\n";
|
||||
}
|
||||
return (PPDependableFile *)NULL;
|
||||
}
|
||||
|
||||
PPDirectoryTree *tree = _directory->get_tree();
|
||||
|
||||
bool okcircular = false;
|
||||
string line;
|
||||
getline(in, line);
|
||||
while (!in.fail() && !in.eof()) {
|
||||
if (line.substr(0, 16) == "/* okcircular */") {
|
||||
okcircular = true;
|
||||
} else {
|
||||
string filename = check_include(line);
|
||||
if (!filename.empty() && filename.find('/') == string::npos) {
|
||||
Dependency dep;
|
||||
dep._okcircular = okcircular;
|
||||
dep._file = tree->find_dependable_file(filename);
|
||||
if (dep._file != (PPDependableFile *)NULL) {
|
||||
// All right! Here's a file we depend on. Add it to the
|
||||
// list.
|
||||
_dependencies.push_back(dep);
|
||||
|
||||
} else {
|
||||
// It's an include file from somewhere else, not from within
|
||||
// our source tree. We don't care about it, but we do need
|
||||
// to record it so we can easily check later if the cache
|
||||
// file has gone stale.
|
||||
_extra_includes.push_back(filename);
|
||||
}
|
||||
}
|
||||
okcircular = false;
|
||||
}
|
||||
getline(in, line);
|
||||
}
|
||||
}
|
||||
|
||||
// Now recursively expand all our dependent files, so we can check
|
||||
// for circularities.
|
||||
PPDependableFile *circ = (PPDependableFile *)NULL;
|
||||
|
||||
Dependencies::iterator di;
|
||||
for (di = _dependencies.begin();
|
||||
di != _dependencies.end() && circ == (PPDependableFile *)NULL;
|
||||
++di) {
|
||||
// Skip this file if the user specifically marked it
|
||||
// with an "okcircular" comment.
|
||||
if (!(*di)._okcircular) {
|
||||
circ = (*di)._file->compute_dependencies(circularity);
|
||||
if (circ != (PPDependableFile *)NULL) {
|
||||
// Oops, a circularity. Silly user.
|
||||
circularity = get_dirpath() + " => " + circularity;
|
||||
|
||||
if (circ == this) {
|
||||
_flags |= F_circularity;
|
||||
_circularity = circularity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_flags = (_flags & ~F_updating) | F_updated;
|
||||
return circ;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDependableFile::stat_file
|
||||
// Access: Private
|
||||
// Description: Performs a stat() on the file, if it has not already
|
||||
// been performed, to check whether the file exists and
|
||||
// to get its last-modification time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDependableFile::
|
||||
stat_file() {
|
||||
if ((_flags & F_statted) != 0) {
|
||||
// Already done.
|
||||
return;
|
||||
}
|
||||
|
||||
_flags |= F_statted;
|
||||
struct stat st;
|
||||
if (stat(get_pathname().c_str(), &st) < 0) {
|
||||
// The file doesn't exist!
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
// The file exists, but it's not a regular file--we consider that
|
||||
// not existing.
|
||||
return;
|
||||
}
|
||||
|
||||
_flags |= F_exists;
|
||||
_mtime = st.st_mtime;
|
||||
}
|
||||
83
ppremake/ppDependableFile.h
Normal file
83
ppremake/ppDependableFile.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// Filename: ppDependableFile.h
|
||||
// Created by: drose (15Oct00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PPDEPENDABLEFILE_H
|
||||
#define PPDEPENDABLEFILE_H
|
||||
|
||||
#include "ppremake.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class PPDirectory;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : PPDependableFile
|
||||
// Description : Corresponds to a single C/C++ source file, either a
|
||||
// .c file or a .h file, that can be scanned for a
|
||||
// number of #include statements. This file may both
|
||||
// depend on other files, as well as being depended upon
|
||||
// in turn. This is used to resolved inter-file
|
||||
// dependencies.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PPDependableFile {
|
||||
public:
|
||||
PPDependableFile(PPDirectory *directory, const string &filename);
|
||||
void update_from_cache(const vector<string> &words);
|
||||
void write_cache(ostream &out);
|
||||
|
||||
PPDirectory *get_directory() const;
|
||||
const string &get_filename() const;
|
||||
string get_pathname() const;
|
||||
string get_dirpath() const;
|
||||
|
||||
bool exists();
|
||||
time_t get_mtime();
|
||||
|
||||
int get_num_dependencies();
|
||||
PPDependableFile *get_dependency(int n);
|
||||
|
||||
void get_complete_dependencies(set<PPDependableFile *> &files);
|
||||
|
||||
bool is_circularity();
|
||||
string get_circularity();
|
||||
|
||||
bool was_examined() const;
|
||||
|
||||
private:
|
||||
void update_dependencies();
|
||||
PPDependableFile *compute_dependencies(string &circularity);
|
||||
void stat_file();
|
||||
|
||||
PPDirectory *_directory;
|
||||
string _filename;
|
||||
|
||||
enum Flags {
|
||||
F_updating = 0x001,
|
||||
F_updated = 0x002,
|
||||
F_circularity = 0x004,
|
||||
F_statted = 0x008,
|
||||
F_exists = 0x010,
|
||||
F_from_cache = 0x020,
|
||||
};
|
||||
int _flags;
|
||||
string _circularity;
|
||||
time_t _mtime;
|
||||
|
||||
class Dependency {
|
||||
public:
|
||||
PPDependableFile *_file;
|
||||
bool _okcircular;
|
||||
};
|
||||
|
||||
typedef vector<Dependency> Dependencies;
|
||||
Dependencies _dependencies;
|
||||
|
||||
typedef vector<string> ExtraIncludes;
|
||||
ExtraIncludes _extra_includes;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
779
ppremake/ppDirectory.cxx
Normal file
779
ppremake/ppDirectory.cxx
Normal file
@@ -0,0 +1,779 @@
|
||||
// Filename: ppDirectory.cxx
|
||||
// Created by: drose (28Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ppDirectory.h"
|
||||
#include "ppDirectoryTree.h"
|
||||
#include "ppScope.h"
|
||||
#include "ppNamedScopes.h"
|
||||
#include "ppCommandFile.h"
|
||||
#include "ppDependableFile.h"
|
||||
#include "tokenize.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
PPDirectory *current_output_directory = (PPDirectory *)NULL;
|
||||
|
||||
// An STL object to sort directories in order by dependency and then
|
||||
// by name, used in get_child_dirnames().
|
||||
class SortDirectoriesByDependencyAndName {
|
||||
public:
|
||||
bool operator () (const PPDirectory *a, const PPDirectory *b) const {
|
||||
if (a->get_depends_index() != b->get_depends_index()) {
|
||||
return a->get_depends_index() < b->get_depends_index();
|
||||
}
|
||||
return a->get_dirname() < b->get_dirname();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::Constructor
|
||||
// Access: Public
|
||||
// Description: Creates the root directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectory::
|
||||
PPDirectory(PPDirectoryTree *tree) {
|
||||
_scope = (PPScope *)NULL;
|
||||
_source = (PPCommandFile *)NULL;
|
||||
_parent = (PPDirectory *)NULL;
|
||||
_tree = tree;
|
||||
_depth = 0;
|
||||
_depends_index = 0;
|
||||
_computing_depends_index = false;
|
||||
|
||||
_dirname = "top";
|
||||
_tree->_dirnames.insert(PPDirectoryTree::Dirnames::value_type(_dirname, this));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::Constructor
|
||||
// Access: Public
|
||||
// Description: Creates a new directory level that automatically adds
|
||||
// itself to its parent's children list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectory::
|
||||
PPDirectory(const string &dirname, PPDirectory *parent) :
|
||||
_dirname(dirname),
|
||||
_parent(parent)
|
||||
{
|
||||
assert(_parent != (PPDirectory *)NULL);
|
||||
_scope = (PPScope *)NULL;
|
||||
_source = (PPCommandFile *)NULL;
|
||||
_parent->_children.push_back(this);
|
||||
_tree = _parent->_tree;
|
||||
_depth = _parent->_depth + 1;
|
||||
_depends_index = 0;
|
||||
_computing_depends_index = false;
|
||||
|
||||
bool inserted =
|
||||
_tree->_dirnames.insert(PPDirectoryTree::Dirnames::value_type(_dirname, this)).second;
|
||||
if (!inserted) {
|
||||
cerr << "Warning: multiple directories encountered named "
|
||||
<< _dirname << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::Destructor
|
||||
// Access: Public
|
||||
// Description: When a tree root destructs, all of its children are
|
||||
// also destroyed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectory::
|
||||
~PPDirectory() {
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
delete (*ci);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_tree
|
||||
// Access: Public
|
||||
// Description: Returns the PPDirectoryTree object corresponding to
|
||||
// the source tree that this directory is a part of.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectoryTree *PPDirectory::
|
||||
get_tree() const {
|
||||
return _tree;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::count_source_files
|
||||
// Access: Public
|
||||
// Description: Returns the number of directories within the tree
|
||||
// that actually have a Sources.pp file that was read.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPDirectory::
|
||||
count_source_files() const {
|
||||
int count = 0;
|
||||
if (_source != (PPCommandFile *)NULL) {
|
||||
count++;
|
||||
}
|
||||
|
||||
Children::const_iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
count += (*ci)->count_source_files();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_dirname
|
||||
// Access: Public
|
||||
// Description: Returns the name of this particular directory level.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &PPDirectory::
|
||||
get_dirname() const {
|
||||
return _dirname;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_depends_index
|
||||
// Access: Public
|
||||
// Description: Returns the dependency index associated with this
|
||||
// directory. It is generally true that if directory A
|
||||
// depends on B, then A.get_depends_index() >
|
||||
// B.get_depends_index().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPDirectory::
|
||||
get_depends_index() const {
|
||||
return _depends_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_path
|
||||
// Access: Public
|
||||
// Description: Returns the relative path from the root to this
|
||||
// particular directory. This does not include the root
|
||||
// name itself, and does not include a trailing slash.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectory::
|
||||
get_path() const {
|
||||
if (_parent == (PPDirectory *)NULL) {
|
||||
return ".";
|
||||
}
|
||||
if (_parent->_parent == (PPDirectory *)NULL) {
|
||||
return _dirname;
|
||||
}
|
||||
return _parent->get_path() + "/" + _dirname;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_rel_to
|
||||
// Access: Public
|
||||
// Description: Returns the relative path to the other directory from
|
||||
// this one. This does not include a trailing slash.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectory::
|
||||
get_rel_to(const PPDirectory *other) const {
|
||||
const PPDirectory *a = this;
|
||||
const PPDirectory *b = other;
|
||||
|
||||
if (a == b) {
|
||||
return ".";
|
||||
}
|
||||
|
||||
string prefix, postfix;
|
||||
while (a->_depth > b->_depth) {
|
||||
prefix += "../";
|
||||
a = a->_parent;
|
||||
assert(a != (PPDirectory *)NULL);
|
||||
}
|
||||
|
||||
while (b->_depth > a->_depth) {
|
||||
postfix = b->_dirname + "/" + postfix;
|
||||
b = b->_parent;
|
||||
assert(b != (PPDirectory *)NULL);
|
||||
}
|
||||
|
||||
while (a != b) {
|
||||
prefix += "../";
|
||||
postfix = b->_dirname + "/" + postfix;
|
||||
a = a->_parent;
|
||||
b = b->_parent;
|
||||
assert(a != (PPDirectory *)NULL);
|
||||
assert(b != (PPDirectory *)NULL);
|
||||
}
|
||||
|
||||
string result = prefix + postfix;
|
||||
assert(!result.empty());
|
||||
return result.substr(0, result.length() - 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_source
|
||||
// Access: Public
|
||||
// Description: Returns the source file associated with this level
|
||||
// of the directory hierarchy. This *might* be NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPCommandFile *PPDirectory::
|
||||
get_source() const {
|
||||
return _source;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_num_children
|
||||
// Access: Public
|
||||
// Description: Returns the number of subdirectories below this
|
||||
// level.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPDirectory::
|
||||
get_num_children() const {
|
||||
return _children.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_child
|
||||
// Access: Public
|
||||
// Description: Returns the nth subdirectory below this level.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectory *PPDirectory::
|
||||
get_child(int n) const {
|
||||
assert(n >= 0 && n < (int)_children.size());
|
||||
return _children[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_child_dirnames
|
||||
// Access: Public
|
||||
// Description: Returns a single string listing the names of all the
|
||||
// subdirectories of this level, delimited by spaces.
|
||||
//
|
||||
// The list is sorted in dependency order such that a
|
||||
// directory is listed after the other directories it
|
||||
// might depend on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectory::
|
||||
get_child_dirnames() const {
|
||||
Children copy_children = _children;
|
||||
sort(copy_children.begin(), copy_children.end(),
|
||||
SortDirectoriesByDependencyAndName());
|
||||
|
||||
vector<string> words;
|
||||
Children::const_iterator ci;
|
||||
for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
|
||||
words.push_back((*ci)->get_dirname());
|
||||
}
|
||||
|
||||
string result = repaste(words, " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_complete_subtree
|
||||
// Access: Public
|
||||
// Description: Returns a single string listing the relative path
|
||||
// from the source root to each source directory at this
|
||||
// level and below, delimited by spaces.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectory::
|
||||
get_complete_subtree() const {
|
||||
Children copy_children = _children;
|
||||
sort(copy_children.begin(), copy_children.end(),
|
||||
SortDirectoriesByDependencyAndName());
|
||||
|
||||
vector<string> words;
|
||||
words.push_back(get_path());
|
||||
|
||||
Children::const_iterator ci;
|
||||
for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
|
||||
words.push_back((*ci)->get_complete_subtree());
|
||||
}
|
||||
|
||||
string result = repaste(words, " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_dependable_file
|
||||
// Access: Public
|
||||
// Description: Returns a PPDependableFile object corresponding to
|
||||
// the named filename, creating one if it does not
|
||||
// already exist. This can be used to determine the
|
||||
// inter-file dependencies between source files.
|
||||
//
|
||||
// If is_header is true, then the file will be added to
|
||||
// the index at the top of the directory tree, so that
|
||||
// other directories may include this file. In this
|
||||
// case, if the filename is not unique, a warning
|
||||
// message will be issued.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDependableFile *PPDirectory::
|
||||
get_dependable_file(const string &filename, bool is_header) {
|
||||
Dependables::iterator di;
|
||||
di = _dependables.find(filename);
|
||||
if (di != _dependables.end()) {
|
||||
return (*di).second;
|
||||
}
|
||||
|
||||
// No such file found; create a new definition.
|
||||
PPDependableFile *dependable = new PPDependableFile(this, filename);
|
||||
_dependables.insert(Dependables::value_type(filename, dependable));
|
||||
|
||||
if (is_header) {
|
||||
bool unique = _tree->_dependables.insert
|
||||
(PPDirectoryTree::Dependables::value_type(filename, dependable)).second;
|
||||
|
||||
if (!unique) {
|
||||
cerr << "Warning: source file " << dependable->get_pathname()
|
||||
<< " may be confused with "
|
||||
<< _tree->find_dependable_file(filename)->get_pathname()
|
||||
<< ".\n";
|
||||
}
|
||||
}
|
||||
|
||||
return dependable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::report_depends
|
||||
// Access: Public
|
||||
// Description: Reports all the directories that the current
|
||||
// directory depends on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDirectory::
|
||||
report_depends() const {
|
||||
if (_i_depend_on.empty()) {
|
||||
cerr << _dirname << " depends on no other directories.\n";
|
||||
|
||||
} else {
|
||||
// Get the complete set of directories we depend on.
|
||||
Depends dep;
|
||||
get_complete_i_depend_on(dep);
|
||||
|
||||
// Copy the set into a vector, so we can sort it into a nice order
|
||||
// for the user's pleasure.
|
||||
vector<PPDirectory *> dirs;
|
||||
copy(dep.begin(), dep.end(),
|
||||
back_insert_iterator<vector<PPDirectory *> >(dirs));
|
||||
|
||||
sort(dirs.begin(), dirs.end(), SortDirectoriesByDependencyAndName());
|
||||
|
||||
cerr << _dirname << " depends on the following directories:";
|
||||
static const int max_col = 72;
|
||||
int col = max_col;
|
||||
vector<PPDirectory *>::const_iterator di;
|
||||
for (di = dirs.begin(); di != dirs.end(); ++di) {
|
||||
const string &dirname = (*di)->_dirname;
|
||||
col += dirname.length() + 1;
|
||||
if (col >= max_col) {
|
||||
col = dirname.length() + 2;
|
||||
cerr << "\n " << dirname;
|
||||
} else {
|
||||
cerr << " " << dirname;
|
||||
}
|
||||
}
|
||||
cerr << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::report_needs
|
||||
// Access: Public
|
||||
// Description: Reports all the directories that depend on (need) the
|
||||
// current directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDirectory::
|
||||
report_needs() const {
|
||||
if (_depends_on_me.empty()) {
|
||||
cerr << _dirname << " is needed by no other directories.\n";
|
||||
|
||||
} else {
|
||||
// Get the complete set of directories we depend on.
|
||||
Depends dep;
|
||||
get_complete_depends_on_me(dep);
|
||||
|
||||
// Copy the set into a vector, so we can sort it into a nice order
|
||||
// for the user's pleasure.
|
||||
vector<PPDirectory *> dirs;
|
||||
copy(dep.begin(), dep.end(),
|
||||
back_insert_iterator<vector<PPDirectory *> >(dirs));
|
||||
|
||||
sort(dirs.begin(), dirs.end(), SortDirectoriesByDependencyAndName());
|
||||
|
||||
cerr << _dirname << " is needed by the following directories:";
|
||||
static const int max_col = 72;
|
||||
int col = max_col;
|
||||
vector<PPDirectory *>::const_iterator di;
|
||||
for (di = dirs.begin(); di != dirs.end(); ++di) {
|
||||
const string &dirname = (*di)->_dirname;
|
||||
col += dirname.length() + 1;
|
||||
if (col >= max_col) {
|
||||
col = dirname.length() + 2;
|
||||
cerr << "\n " << dirname;
|
||||
} else {
|
||||
cerr << " " << dirname;
|
||||
}
|
||||
}
|
||||
cerr << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::r_scan
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of scan_source().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectory::
|
||||
r_scan(const string &prefix) {
|
||||
string root_name = ".";
|
||||
if (!prefix.empty()) {
|
||||
root_name = prefix.substr(0, prefix.length() - 1);
|
||||
}
|
||||
|
||||
DIR *root = opendir(root_name.c_str());
|
||||
if (root == (DIR *)NULL) {
|
||||
cerr << "Unable to scan directory " << root_name << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dirent *d;
|
||||
d = readdir(root);
|
||||
while (d != (struct dirent *)NULL) {
|
||||
string filename = d->d_name;
|
||||
|
||||
if (!filename.empty() && filename[0] != '.') {
|
||||
// Is this possibly a subdirectory with its own Sources.pp
|
||||
// within it?
|
||||
string next_prefix = prefix + filename + "/";
|
||||
string source_filename = next_prefix + SOURCE_FILENAME;
|
||||
if (access(source_filename.c_str(), F_OK) == 0) {
|
||||
PPDirectory *subtree = new PPDirectory(filename, this);
|
||||
|
||||
if (!subtree->r_scan(next_prefix)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d = readdir(root);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::read_source_file
|
||||
// Access: Private
|
||||
// Description: Recursively reads in the source file at each level,
|
||||
// if defined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectory::
|
||||
read_source_file(const string &prefix, PPNamedScopes *named_scopes) {
|
||||
string source_filename = prefix + SOURCE_FILENAME;
|
||||
|
||||
ifstream in(source_filename.c_str());
|
||||
if (in) {
|
||||
// cerr << "Reading " << source_filename << "\n";
|
||||
|
||||
named_scopes->set_current(_dirname);
|
||||
_scope = named_scopes->make_scope("");
|
||||
|
||||
_scope->define_variable("SOURCEFILE", SOURCE_FILENAME);
|
||||
_scope->define_variable("DIRNAME", _dirname);
|
||||
_scope->define_variable("DIRPREFIX", prefix);
|
||||
_scope->define_variable("PATH", get_path());
|
||||
_scope->define_variable("SUBDIRS", get_child_dirnames());
|
||||
_scope->define_variable("SUBTREE", get_complete_subtree());
|
||||
_scope->set_directory(this);
|
||||
|
||||
_source = new PPCommandFile(_scope);
|
||||
|
||||
if (!_source->read_stream(in)) {
|
||||
cerr << "Error when reading " << source_filename << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
if (!(*ci)->read_source_file(prefix + (*ci)->get_dirname() + "/",
|
||||
named_scopes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::read_depends_file
|
||||
// Access: Private
|
||||
// Description: Recursively reads in the dependency definition file
|
||||
// for each source file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectory::
|
||||
read_depends_file(PPNamedScopes *named_scopes) {
|
||||
if (_scope != (PPScope *)NULL) {
|
||||
// Read the depends file, so we can determine the relationship
|
||||
// between this source file and all of the other source files.
|
||||
|
||||
string depends_filename = _scope->expand_variable("DEPENDS_FILE");
|
||||
if (depends_filename.empty()) {
|
||||
cerr << "No definition given for $[DEPENDS_FILE], cannot process.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
named_scopes->set_current(_dirname);
|
||||
PPCommandFile depends(_scope);
|
||||
if (!depends.read_file(depends_filename)) {
|
||||
cerr << "Error reading dependency definition file "
|
||||
<< depends_filename << ".\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// This should have defined the variable DEPEND_DIRS, which lists
|
||||
// the various dirnames this source file depends on.
|
||||
|
||||
vector<string> dirnames;
|
||||
tokenize_whitespace(_scope->expand_variable("DEPEND_DIRS"), dirnames);
|
||||
|
||||
vector<string>::const_iterator ni;
|
||||
for (ni = dirnames.begin(); ni != dirnames.end(); ++ni) {
|
||||
const string &dirname = (*ni);
|
||||
PPDirectory *dir = _tree->find_dirname(dirname);
|
||||
if (dir == (PPDirectory *)NULL) {
|
||||
cerr << "Could not find dependent dirname " << dirname << "\n";
|
||||
} else {
|
||||
if (dir != this) {
|
||||
_i_depend_on.insert(dir);
|
||||
dir->_depends_on_me.insert(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This may also have defined the variable DEPENDABLE_HEADERS,
|
||||
// which lists the header files in this directory that C/C++
|
||||
// source files in this and other directories might be including
|
||||
// (and will therefore depend on).
|
||||
vector<string> headers;
|
||||
tokenize_whitespace(_scope->expand_variable("DEPENDABLE_HEADERS"), headers);
|
||||
for (ni = headers.begin(); ni != headers.end(); ++ni) {
|
||||
get_dependable_file(*ni, true);
|
||||
}
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
if (!(*ci)->read_depends_file(named_scopes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::resolve_dependencies
|
||||
// Access: Private
|
||||
// Description: Visits each directory and assigns a correct
|
||||
// _depends_index to each one, such that if directory A
|
||||
// depends on directory B then A._depends_index >
|
||||
// B._depends_index.
|
||||
//
|
||||
// This also detects cycles in the directory dependency
|
||||
// graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectory::
|
||||
resolve_dependencies() {
|
||||
if (!compute_depends_index()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
if (!(*ci)->resolve_dependencies()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've resolved all of our children's dependencies,
|
||||
// redefine our SUBDIRS and SUBTREE variables to put things in the
|
||||
// right order.
|
||||
if (_scope != (PPScope *)NULL) {
|
||||
_scope->define_variable("SUBDIRS", get_child_dirnames());
|
||||
_scope->define_variable("SUBTREE", get_complete_subtree());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::compute_depends_index
|
||||
// Access: Private
|
||||
// Description: Computes the dependency score for a particular
|
||||
// directory. See resolve_dependencies().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectory::
|
||||
compute_depends_index() {
|
||||
if (_depends_index != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_i_depend_on.empty()) {
|
||||
_depends_index = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
_computing_depends_index = true;
|
||||
int max_index = 0;
|
||||
|
||||
Depends::iterator di;
|
||||
for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
|
||||
if ((*di)->_computing_depends_index) {
|
||||
// Oops, we have a cycle!
|
||||
cerr << "Cycle detected in inter-directory dependencies!\n"
|
||||
<< _dirname << " depends on " << (*di)->_dirname << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(*di)->compute_depends_index()) {
|
||||
// Keep reporting the cycle as we unroll the recursion.
|
||||
cerr << _dirname << " depends on " << (*di)->_dirname << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
max_index = max(max_index, (*di)->_depends_index);
|
||||
}
|
||||
|
||||
_computing_depends_index = false;
|
||||
_depends_index = max_index + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::read_file_dependencies
|
||||
// Access: Private
|
||||
// Description: Before processing the source files, makes a pass and
|
||||
// reads in all of the dependency cache files so we'll
|
||||
// have a heads-up on which files depend on the others.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDirectory::
|
||||
read_file_dependencies(const string &cache_filename) {
|
||||
// Open up the dependency cache file in the directory.
|
||||
string cache_pathname = get_path() + "/" + cache_filename;
|
||||
ifstream in(cache_pathname.c_str());
|
||||
if (!in) {
|
||||
// Can't read it. Maybe it's not there. No problem.
|
||||
return;
|
||||
}
|
||||
|
||||
string line;
|
||||
getline(in, line);
|
||||
while (!in.fail() && !in.eof()) {
|
||||
vector<string> words;
|
||||
tokenize_whitespace(line, words);
|
||||
if (words.size() >= 2) {
|
||||
PPDependableFile *file = get_dependable_file(words[0], false);
|
||||
file->update_from_cache(words);
|
||||
}
|
||||
getline(in, line);
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
(*ci)->read_file_dependencies(cache_filename);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::update_file_dependencies
|
||||
// Access: Private
|
||||
// Description: After all source processing has completed, makes one
|
||||
// more pass through the directory hierarchy and writes
|
||||
// out the inter-file dependency cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDirectory::
|
||||
update_file_dependencies(const string &cache_filename) {
|
||||
// Open up the dependency cache file in the directory.
|
||||
string cache_pathname = get_path() + "/" + cache_filename;
|
||||
unlink(cache_pathname.c_str());
|
||||
|
||||
// If we have no files, don't bother writing the cache.
|
||||
if (!_dependables.empty()) {
|
||||
bool wrote_anything = false;
|
||||
|
||||
ofstream out(cache_pathname.c_str(), ios::out, 0666);
|
||||
if (!out) {
|
||||
cerr << "Cannot update cache dependency file " << cache_pathname << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Walk through our list of dependable files, writing them out the
|
||||
// the cache file.
|
||||
Dependables::const_iterator di;
|
||||
for (di = _dependables.begin(); di != _dependables.end(); ++di) {
|
||||
PPDependableFile *file = (*di).second;
|
||||
if (file->was_examined()) {
|
||||
if (file->is_circularity()) {
|
||||
cerr << "Warning: circular #include directives:\n"
|
||||
<< " " << file->get_circularity() << "\n";
|
||||
}
|
||||
file->write_cache(out);
|
||||
wrote_anything = true;
|
||||
}
|
||||
}
|
||||
|
||||
out.close();
|
||||
|
||||
if (!wrote_anything) {
|
||||
// Well, if we didn't write anything, remove the cache file
|
||||
// after all.
|
||||
unlink(cache_pathname.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
(*ci)->update_file_dependencies(cache_filename);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_complete_i_depend_on
|
||||
// Access: Private
|
||||
// Description: Gets the transitive closure of i_depend_on. This
|
||||
// fills the given set (which must have been empty
|
||||
// before this call) with the complete set of all
|
||||
// directories this directory depends on, directly or
|
||||
// indirectly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDirectory::
|
||||
get_complete_i_depend_on(Depends &dep) const {
|
||||
Depends::const_iterator di;
|
||||
for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
|
||||
PPDirectory *dir = (*di);
|
||||
bool inserted = dep.insert(dir).second;
|
||||
if (inserted) {
|
||||
dir->get_complete_i_depend_on(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectory::get_complete_depends_on_me
|
||||
// Access: Private
|
||||
// Description: Gets the transitive closure of depends_on_me. This
|
||||
// fills the given set (which must have been empty
|
||||
// before this call) with the complete set of all
|
||||
// directories this that depend on this directory,
|
||||
// directly or indirectly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPDirectory::
|
||||
get_complete_depends_on_me(Depends &dep) const {
|
||||
Depends::const_iterator di;
|
||||
for (di = _depends_on_me.begin(); di != _depends_on_me.end(); ++di) {
|
||||
PPDirectory *dir = (*di);
|
||||
bool inserted = dep.insert(dir).second;
|
||||
if (inserted) {
|
||||
dir->get_complete_depends_on_me(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
94
ppremake/ppDirectory.h
Normal file
94
ppremake/ppDirectory.h
Normal file
@@ -0,0 +1,94 @@
|
||||
// Filename: ppDirectory.h
|
||||
// Created by: drose (28Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PPDIRECTORY_H
|
||||
#define PPDIRECTORY_H
|
||||
|
||||
#include "ppremake.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
class PPCommandFile;
|
||||
class PPScope;
|
||||
class PPNamedScopes;
|
||||
class PPDirectoryTree;
|
||||
class PPDependableFile;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : PPDirectory
|
||||
// Description : Represents a single directory in the source
|
||||
// hierarchy. Each PPDirectory object is one-to-one
|
||||
// associated with a PPCommandFile object, that
|
||||
// corresponds to the source file found within this
|
||||
// directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PPDirectory {
|
||||
public:
|
||||
PPDirectory(PPDirectoryTree *tree);
|
||||
PPDirectory(const string &dirname, PPDirectory *parent);
|
||||
~PPDirectory();
|
||||
|
||||
PPDirectoryTree *get_tree() const;
|
||||
int count_source_files() const;
|
||||
|
||||
const string &get_dirname() const;
|
||||
int get_depends_index() const;
|
||||
string get_path() const;
|
||||
string get_rel_to(const PPDirectory *other) const;
|
||||
|
||||
PPCommandFile *get_source() const;
|
||||
|
||||
int get_num_children() const;
|
||||
PPDirectory *get_child(int n) const;
|
||||
|
||||
string get_child_dirnames() const;
|
||||
string get_complete_subtree() const;
|
||||
|
||||
PPDependableFile *get_dependable_file(const string &filename,
|
||||
bool is_header);
|
||||
|
||||
void report_depends() const;
|
||||
void report_needs() const;
|
||||
|
||||
private:
|
||||
typedef set<PPDirectory *> Depends;
|
||||
|
||||
bool r_scan(const string &prefix);
|
||||
bool read_source_file(const string &prefix, PPNamedScopes *named_scopes);
|
||||
bool read_depends_file(PPNamedScopes *named_scopes);
|
||||
bool resolve_dependencies();
|
||||
bool compute_depends_index();
|
||||
void read_file_dependencies(const string &cache_filename);
|
||||
void update_file_dependencies(const string &cache_filename);
|
||||
|
||||
void get_complete_i_depend_on(Depends &dep) const;
|
||||
void get_complete_depends_on_me(Depends &dep) const;
|
||||
|
||||
string _dirname;
|
||||
PPScope *_scope;
|
||||
PPCommandFile *_source;
|
||||
PPDirectory *_parent;
|
||||
PPDirectoryTree *_tree;
|
||||
typedef vector<PPDirectory *> Children;
|
||||
Children _children;
|
||||
int _depth;
|
||||
|
||||
Depends _i_depend_on;
|
||||
Depends _depends_on_me;
|
||||
int _depends_index;
|
||||
bool _computing_depends_index;
|
||||
|
||||
typedef map<string, PPDependableFile *> Dependables;
|
||||
Dependables _dependables;
|
||||
|
||||
friend class PPDirectoryTree;
|
||||
};
|
||||
|
||||
extern PPDirectory *current_output_directory;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,89 +4,26 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ppDirectoryTree.h"
|
||||
#include "ppScope.h"
|
||||
#include "ppNamedScopes.h"
|
||||
#include "ppCommandFile.h"
|
||||
#include "tokenize.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
PPDirectoryTree *current_output_directory = (PPDirectoryTree *)NULL;
|
||||
|
||||
// An STL object to sort directories in order by dependency and then
|
||||
// by name, used in get_child_dirnames().
|
||||
class SortDirectoriesByDependencyAndName {
|
||||
public:
|
||||
bool operator () (const PPDirectoryTree *a, const PPDirectoryTree *b) const {
|
||||
if (a->get_depends_index() != b->get_depends_index()) {
|
||||
return a->get_depends_index() < b->get_depends_index();
|
||||
}
|
||||
return a->get_dirname() < b->get_dirname();
|
||||
}
|
||||
};
|
||||
#include "ppDirectory.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::Constructor
|
||||
// Access: Public
|
||||
// Description: Creates the root level of the PPDirectoryTree.
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectoryTree::
|
||||
PPDirectoryTree() {
|
||||
_scope = (PPScope *)NULL;
|
||||
_source = (PPCommandFile *)NULL;
|
||||
_parent = (PPDirectoryTree *)NULL;
|
||||
_depth = 0;
|
||||
_depends_index = 0;
|
||||
_computing_depends_index = false;
|
||||
_dirnames = new Dirnames;
|
||||
|
||||
_dirname = "top";
|
||||
(*_dirnames).insert(Dirnames::value_type(_dirname, this));
|
||||
_root = new PPDirectory(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::Destructor
|
||||
// Access: Public
|
||||
// Description: When a tree root destructs, all of its children are
|
||||
// also destroyed.
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectoryTree::
|
||||
~PPDirectoryTree() {
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
delete (*ci);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::Constructor
|
||||
// Access: Protected
|
||||
// Description: Creates a new directory level that automatically adds
|
||||
// itself to its parent's children list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectoryTree::
|
||||
PPDirectoryTree(const string &dirname, PPDirectoryTree *parent) :
|
||||
_dirname(dirname),
|
||||
_parent(parent)
|
||||
{
|
||||
assert(_parent != (PPDirectoryTree *)NULL);
|
||||
_scope = (PPScope *)NULL;
|
||||
_source = (PPCommandFile *)NULL;
|
||||
_parent->_children.push_back(this);
|
||||
_depth = _parent->_depth + 1;
|
||||
_depends_index = 0;
|
||||
_computing_depends_index = false;
|
||||
_dirnames = _parent->_dirnames;
|
||||
|
||||
bool inserted =
|
||||
(*_dirnames).insert(Dirnames::value_type(_dirname, this)).second;
|
||||
if (!inserted) {
|
||||
cerr << "Warning: multiple directories encountered named "
|
||||
<< _dirname << "\n";
|
||||
}
|
||||
delete _root;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -97,11 +34,11 @@ PPDirectoryTree(const string &dirname, PPDirectoryTree *parent) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectoryTree::
|
||||
scan_source(PPNamedScopes *named_scopes) {
|
||||
if (!r_scan("")) {
|
||||
if (!_root->r_scan("")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!read_source_file("", named_scopes)) {
|
||||
if (!_root->read_source_file("", named_scopes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,11 +53,11 @@ scan_source(PPNamedScopes *named_scopes) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectoryTree::
|
||||
scan_depends(PPNamedScopes *named_scopes) {
|
||||
if (!read_depends_file(named_scopes)) {
|
||||
if (!_root->read_depends_file(named_scopes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!resolve_dependencies()) {
|
||||
if (!_root->resolve_dependencies()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -135,426 +72,130 @@ scan_depends(PPNamedScopes *named_scopes) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPDirectoryTree::
|
||||
count_source_files() const {
|
||||
int count = 0;
|
||||
if (_source != (PPCommandFile *)NULL) {
|
||||
count++;
|
||||
}
|
||||
|
||||
Children::const_iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
count += (*ci)->count_source_files();
|
||||
}
|
||||
|
||||
return count;
|
||||
return _root->count_source_files();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_dirname
|
||||
// Function: PPDirectoryTree::get_root
|
||||
// Access: Public
|
||||
// Description: Returns the name of this particular directory level.
|
||||
// Description: Returns the root directory of the tree.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &PPDirectoryTree::
|
||||
get_dirname() const {
|
||||
return _dirname;
|
||||
PPDirectory *PPDirectoryTree::
|
||||
get_root() const {
|
||||
return _root;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_depends_index
|
||||
// Function: PPDirectoryTree::get_complete_tree
|
||||
// Access: Public
|
||||
// Description: Returns the dependency index associated with this
|
||||
// directory. It is generally true that if directory A
|
||||
// depends on B, then A.get_depends_index() >
|
||||
// B.get_depends_index().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPDirectoryTree::
|
||||
get_depends_index() const {
|
||||
return _depends_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_path
|
||||
// Access: Public
|
||||
// Description: Returns the relative path from the root to this
|
||||
// particular directory. This does not include the root
|
||||
// name itself, and does not include a trailing slash.
|
||||
// Description: Returns a single string listing the relative path
|
||||
// from the source root to each source directory in the
|
||||
// tree, delimited by spaces.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectoryTree::
|
||||
get_path() const {
|
||||
if (_parent == (PPDirectoryTree *)NULL) {
|
||||
return ".";
|
||||
}
|
||||
if (_parent->_parent == (PPDirectoryTree *)NULL) {
|
||||
return _dirname;
|
||||
}
|
||||
return _parent->get_path() + "/" + _dirname;
|
||||
get_complete_tree() const {
|
||||
return _root->get_complete_subtree();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_rel_to
|
||||
// Access: Public
|
||||
// Description: Returns the relative path to the other directory from
|
||||
// this one. This does not include a trailing slash.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectoryTree::
|
||||
get_rel_to(const PPDirectoryTree *other) const {
|
||||
const PPDirectoryTree *a = this;
|
||||
const PPDirectoryTree *b = other;
|
||||
|
||||
if (a == b) {
|
||||
return ".";
|
||||
}
|
||||
|
||||
string prefix, postfix;
|
||||
while (a->_depth > b->_depth) {
|
||||
prefix += "../";
|
||||
a = a->_parent;
|
||||
assert(a != (PPDirectoryTree *)NULL);
|
||||
}
|
||||
|
||||
while (b->_depth > a->_depth) {
|
||||
postfix = b->_dirname + "/" + postfix;
|
||||
b = b->_parent;
|
||||
assert(b != (PPDirectoryTree *)NULL);
|
||||
}
|
||||
|
||||
while (a != b) {
|
||||
prefix += "../";
|
||||
postfix = b->_dirname + "/" + postfix;
|
||||
a = a->_parent;
|
||||
b = b->_parent;
|
||||
assert(a != (PPDirectoryTree *)NULL);
|
||||
assert(b != (PPDirectoryTree *)NULL);
|
||||
}
|
||||
|
||||
string result = prefix + postfix;
|
||||
assert(!result.empty());
|
||||
return result.substr(0, result.length() - 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::find_dirname
|
||||
// Access: Public
|
||||
// Description: Searches for the first subdirectory found with the
|
||||
// Description: Searches for the a source directory with the
|
||||
// matching dirname. This is just the name of the
|
||||
// directory itself, not the relative path to the
|
||||
// directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectoryTree *PPDirectoryTree::
|
||||
find_dirname(const string &dirname) {
|
||||
assert(_dirnames != (Dirnames *)NULL);
|
||||
PPDirectory *PPDirectoryTree::
|
||||
find_dirname(const string &dirname) const {
|
||||
Dirnames::const_iterator di;
|
||||
di = _dirnames->find(dirname);
|
||||
if (di != _dirnames->end()) {
|
||||
di = _dirnames.find(dirname);
|
||||
if (di != _dirnames.end()) {
|
||||
return (*di).second;
|
||||
}
|
||||
|
||||
// No such dirname; too bad.
|
||||
return (PPDirectoryTree *)NULL;
|
||||
return (PPDirectory *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_source
|
||||
// Function: PPDirectoryTree::find_dependable_file
|
||||
// Access: Public
|
||||
// Description: Returns the source file associated with this level
|
||||
// of the directory hierarchy. This *might* be NULL.
|
||||
// Description: Returns a PPDependableFile object corresponding to
|
||||
// the named filename, searching all of the known source
|
||||
// subdirectories. This can only find files marked by a
|
||||
// previous call to get_dependable_file() with is_header
|
||||
// set to true. Unlike
|
||||
// get_dependable_file_by_pathname() or
|
||||
// PPDirectory::get_dependable_file(), this does not
|
||||
// create an entry if it does not exist; instead, it
|
||||
// returns NULL if no matching file can be found.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPCommandFile *PPDirectoryTree::
|
||||
get_source() const {
|
||||
return _source;
|
||||
PPDependableFile *PPDirectoryTree::
|
||||
find_dependable_file(const string &filename) const {
|
||||
Dependables::const_iterator di;
|
||||
di = _dependables.find(filename);
|
||||
if (di != _dependables.end()) {
|
||||
return (*di).second;
|
||||
}
|
||||
|
||||
return (PPDependableFile *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_num_children
|
||||
// Function: PPDirectoryTree::get_dependable_file_by_pathname
|
||||
// Access: Public
|
||||
// Description: Returns the number of subdirectories below this
|
||||
// level.
|
||||
// Description: Given a dirname/filename for a particular dependable
|
||||
// filename, return (or create and return) the
|
||||
// corresponding PPDirectoryTree. This is different
|
||||
// from find_dependable_file() in that an explicit
|
||||
// dirname is given, and the entry will be created if
|
||||
// it does not already exist. However, if the directory
|
||||
// name does not exist, nothing is created, and NULL is
|
||||
// returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PPDirectoryTree::
|
||||
get_num_children() const {
|
||||
return _children.size();
|
||||
PPDependableFile *PPDirectoryTree::
|
||||
get_dependable_file_by_dirpath(const string &dirpath, bool is_header) {
|
||||
size_t slash = dirpath.rfind('/');
|
||||
if (slash == string::npos) {
|
||||
// No valid directory name.
|
||||
return (PPDependableFile *)NULL;
|
||||
}
|
||||
|
||||
string dirname = dirpath.substr(0, slash);
|
||||
string filename = dirpath.substr(slash + 1);
|
||||
|
||||
PPDirectory *dir = find_dirname(dirname);
|
||||
if (dir == (PPDirectory *)NULL) {
|
||||
// No valid directory name.
|
||||
return (PPDependableFile *)NULL;
|
||||
}
|
||||
|
||||
return dir->get_dependable_file(filename, is_header);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_child
|
||||
// Function: PPDirectoryTree::read_file_dependencies
|
||||
// Access: Public
|
||||
// Description: Returns the nth subdirectory below this level.
|
||||
// Description: Before processing the source files, makes a pass and
|
||||
// reads in all of the dependency cache files so we'll
|
||||
// have a heads-up on which files depend on the others.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectoryTree *PPDirectoryTree::
|
||||
get_child(int n) const {
|
||||
assert(n >= 0 && n < (int)_children.size());
|
||||
return _children[n];
|
||||
void PPDirectoryTree::
|
||||
read_file_dependencies(const string &cache_filename) {
|
||||
_root->read_file_dependencies(cache_filename);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_child_dirnames
|
||||
// Function: PPDirectoryTree::update_file_dependencies
|
||||
// Access: Public
|
||||
// Description: Returns a single string listing the names of all the
|
||||
// subdirectories of this level, delimited by spaces.
|
||||
//
|
||||
// The list is sorted in dependency order such that a
|
||||
// directory is listed after the other directories it
|
||||
// might depend on.
|
||||
// Description: After all source processing has completed, makes one
|
||||
// more pass through the directory hierarchy and writes
|
||||
// out the inter-file dependency cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectoryTree::
|
||||
get_child_dirnames() const {
|
||||
Children copy_children = _children;
|
||||
sort(copy_children.begin(), copy_children.end(),
|
||||
SortDirectoriesByDependencyAndName());
|
||||
|
||||
vector<string> words;
|
||||
Children::const_iterator ci;
|
||||
for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
|
||||
words.push_back((*ci)->get_dirname());
|
||||
}
|
||||
|
||||
string result = repaste(words, " ");
|
||||
return result;
|
||||
void PPDirectoryTree::
|
||||
update_file_dependencies(const string &cache_filename) {
|
||||
_root->update_file_dependencies(cache_filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::get_complete_subtree
|
||||
// Access: Public
|
||||
// Description: Returns a single string listing the relative path
|
||||
// from the source root to each source directory at this
|
||||
// level and below, delimited by spaces.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPDirectoryTree::
|
||||
get_complete_subtree() const {
|
||||
Children copy_children = _children;
|
||||
sort(copy_children.begin(), copy_children.end(),
|
||||
SortDirectoriesByDependencyAndName());
|
||||
|
||||
vector<string> words;
|
||||
words.push_back(get_path());
|
||||
|
||||
Children::const_iterator ci;
|
||||
for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
|
||||
words.push_back((*ci)->get_complete_subtree());
|
||||
}
|
||||
|
||||
string result = repaste(words, " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::r_scan
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of scan().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectoryTree::
|
||||
r_scan(const string &prefix) {
|
||||
string root_name = ".";
|
||||
if (!prefix.empty()) {
|
||||
root_name = prefix.substr(0, prefix.length() - 1);
|
||||
}
|
||||
|
||||
DIR *root = opendir(root_name.c_str());
|
||||
if (root == (DIR *)NULL) {
|
||||
cerr << "Unable to scan directory " << root_name << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dirent *d;
|
||||
d = readdir(root);
|
||||
while (d != (struct dirent *)NULL) {
|
||||
string dirname = d->d_name;
|
||||
|
||||
if (!dirname.empty() && dirname[0] != '.') {
|
||||
// Do we have a source file in this subdirectory (if it is a
|
||||
// subdirectory)?
|
||||
string next_prefix = prefix + dirname + "/";
|
||||
string source_filename = next_prefix + SOURCE_FILENAME;
|
||||
if (access(source_filename.c_str(), F_OK) == 0) {
|
||||
PPDirectoryTree *subtree = new PPDirectoryTree(dirname, this);
|
||||
|
||||
if (!subtree->r_scan(next_prefix)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d = readdir(root);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::read_source_file
|
||||
// Access: Private
|
||||
// Description: Recursively reads in the source file at each level,
|
||||
// if defined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectoryTree::
|
||||
read_source_file(const string &prefix, PPNamedScopes *named_scopes) {
|
||||
string source_filename = prefix + SOURCE_FILENAME;
|
||||
|
||||
ifstream in(source_filename.c_str());
|
||||
if (in) {
|
||||
// cerr << "Reading " << source_filename << "\n";
|
||||
|
||||
named_scopes->set_current(_dirname);
|
||||
_scope = named_scopes->make_scope("");
|
||||
|
||||
_scope->define_variable("SOURCEFILE", SOURCE_FILENAME);
|
||||
_scope->define_variable("DIRNAME", _dirname);
|
||||
_scope->define_variable("DIRPREFIX", prefix);
|
||||
_scope->define_variable("PATH", get_path());
|
||||
_scope->define_variable("SUBDIRS", get_child_dirnames());
|
||||
_scope->define_variable("SUBTREE", get_complete_subtree());
|
||||
_scope->set_directory(this);
|
||||
|
||||
_source = new PPCommandFile(_scope);
|
||||
|
||||
if (!_source->read_stream(in)) {
|
||||
cerr << "Error when reading " << source_filename << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
if (!(*ci)->read_source_file(prefix + (*ci)->get_dirname() + "/",
|
||||
named_scopes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::read_depends_file
|
||||
// Access: Private
|
||||
// Description: Recursively reads in the dependency definition file
|
||||
// for each source file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectoryTree::
|
||||
read_depends_file(PPNamedScopes *named_scopes) {
|
||||
if (_scope != (PPScope *)NULL) {
|
||||
// Read the depends file, so we can determine the relationship
|
||||
// between this source file and all of the other source files.
|
||||
|
||||
string depends_filename = _scope->expand_variable("DEPENDS_FILE");
|
||||
if (depends_filename.empty()) {
|
||||
cerr << "No definition given for $[DEPENDS_FILE], cannot process.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
named_scopes->set_current(_dirname);
|
||||
PPCommandFile depends(_scope);
|
||||
if (!depends.read_file(depends_filename)) {
|
||||
cerr << "Error reading dependency definition file "
|
||||
<< depends_filename << ".\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// This should have defined the variable DEPENDS, which lists the
|
||||
// various dirnames this source file depends on.
|
||||
|
||||
vector<string> dirnames;
|
||||
tokenize_whitespace(_scope->expand_variable("DEPENDS"), dirnames);
|
||||
|
||||
vector<string>::const_iterator ni;
|
||||
for (ni = dirnames.begin(); ni != dirnames.end(); ++ni) {
|
||||
const string &dirname = (*ni);
|
||||
PPDirectoryTree *dir = find_dirname(dirname);
|
||||
if (dir == (PPDirectoryTree *)NULL) {
|
||||
cerr << "Could not find dependent dirname " << dirname << "\n";
|
||||
} else {
|
||||
if (dir != this) {
|
||||
_i_depend_on.insert(dir);
|
||||
dir->_depends_on_me.insert(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
if (!(*ci)->read_depends_file(named_scopes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::resolve_dependencies
|
||||
// Access: Private
|
||||
// Description: Visits each directory and assigns a correct
|
||||
// _depends_index to each one, such that if directory A
|
||||
// depends on directory B then A._depends_index >
|
||||
// B._depends_index.
|
||||
//
|
||||
// This also detects cycles in the directory dependency
|
||||
// graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectoryTree::
|
||||
resolve_dependencies() {
|
||||
if (!compute_depends_index()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
if (!(*ci)->resolve_dependencies()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've resolved all of our children's dependencies,
|
||||
// redefine our SUBDIRS and SUBTREE variables to put things in the
|
||||
// right order.
|
||||
if (_scope != (PPScope *)NULL) {
|
||||
_scope->define_variable("SUBDIRS", get_child_dirnames());
|
||||
_scope->define_variable("SUBTREE", get_complete_subtree());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPDirectoryTree::compute_depends_index
|
||||
// Access: Private
|
||||
// Description: Computes the dependency score for a particular
|
||||
// directory. See resolve_dependencies().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPDirectoryTree::
|
||||
compute_depends_index() {
|
||||
if (_depends_index != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_i_depend_on.empty()) {
|
||||
_depends_index = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
_computing_depends_index = true;
|
||||
int max_index = 0;
|
||||
|
||||
Depends::iterator di;
|
||||
for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
|
||||
if ((*di)->_computing_depends_index) {
|
||||
// Oops, we have a cycle!
|
||||
cerr << "Cycle detected in inter-directory dependencies!\n"
|
||||
<< _dirname << " depends on " << (*di)->_dirname << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(*di)->compute_depends_index()) {
|
||||
// Keep reporting the cycle as we unroll the recursion.
|
||||
cerr << _dirname << " depends on " << (*di)->_dirname << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
max_index = max(max_index, (*di)->_depends_index);
|
||||
}
|
||||
|
||||
_computing_depends_index = false;
|
||||
_depends_index = max_index + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Filename: ppDirectoryTree.h
|
||||
// Created by: drose (28Sep00)
|
||||
// Created by: drose (15Oct00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -8,77 +8,51 @@
|
||||
|
||||
#include "ppremake.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
class PPCommandFile;
|
||||
class PPScope;
|
||||
class PPNamedScopes;
|
||||
class PPDirectory;
|
||||
class PPDependableFile;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : PPDirectoryTree
|
||||
// Description : Stores the directory hierarchy relationship of the
|
||||
// source tree. Each PPDirectoryTree object is
|
||||
// one-to-one associated with a PPCommandFile object,
|
||||
// that corresponds to the source file found within this
|
||||
// directory.
|
||||
// Description : Stores the entire directory hierarchy relationship of the
|
||||
// source tree. This is the root of a tree of
|
||||
// PPDirectory objects, each of which corresponds to a
|
||||
// particular directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PPDirectoryTree {
|
||||
public:
|
||||
PPDirectoryTree();
|
||||
~PPDirectoryTree();
|
||||
|
||||
protected:
|
||||
PPDirectoryTree(const string &dirname, PPDirectoryTree *parent);
|
||||
|
||||
public:
|
||||
bool scan_source(PPNamedScopes *named_scopes);
|
||||
bool scan_depends(PPNamedScopes *named_scopes);
|
||||
|
||||
int count_source_files() const;
|
||||
PPDirectory *get_root() const;
|
||||
|
||||
const string &get_dirname() const;
|
||||
int get_depends_index() const;
|
||||
string get_path() const;
|
||||
string get_rel_to(const PPDirectoryTree *other) const;
|
||||
string get_complete_tree() const;
|
||||
|
||||
PPDirectoryTree *find_dirname(const string &dirname);
|
||||
PPCommandFile *get_source() const;
|
||||
PPDirectory *find_dirname(const string &dirname) const;
|
||||
|
||||
int get_num_children() const;
|
||||
PPDirectoryTree *get_child(int n) const;
|
||||
PPDependableFile *find_dependable_file(const string &filename) const;
|
||||
PPDependableFile *get_dependable_file_by_dirpath(const string &dirpath,
|
||||
bool is_header);
|
||||
|
||||
string get_child_dirnames() const;
|
||||
string get_complete_subtree() const;
|
||||
void read_file_dependencies(const string &cache_filename);
|
||||
void update_file_dependencies(const string &cache_filename);
|
||||
|
||||
private:
|
||||
bool r_scan(const string &prefix);
|
||||
bool read_source_file(const string &prefix, PPNamedScopes *named_scopes);
|
||||
bool read_depends_file(PPNamedScopes *named_scopes);
|
||||
bool resolve_dependencies();
|
||||
bool compute_depends_index();
|
||||
PPDirectory *_root;
|
||||
|
||||
string _dirname;
|
||||
PPScope *_scope;
|
||||
PPCommandFile *_source;
|
||||
PPDirectoryTree *_parent;
|
||||
typedef vector<PPDirectoryTree *> Children;
|
||||
Children _children;
|
||||
int _depth;
|
||||
typedef map<string, PPDirectory *> Dirnames;
|
||||
Dirnames _dirnames;
|
||||
|
||||
typedef set<PPDirectoryTree *> Depends;
|
||||
Depends _i_depend_on;
|
||||
Depends _depends_on_me;
|
||||
int _depends_index;
|
||||
bool _computing_depends_index;
|
||||
typedef map<string, PPDependableFile *> Dependables;
|
||||
Dependables _dependables;
|
||||
|
||||
|
||||
typedef map<string, PPDirectoryTree *> Dirnames;
|
||||
Dirnames *_dirnames;
|
||||
friend class PPDirectory;
|
||||
};
|
||||
|
||||
extern PPDirectoryTree *current_output_directory;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "ppMain.h"
|
||||
#include "ppScope.h"
|
||||
#include "ppCommandFile.h"
|
||||
#include "ppDirectory.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
@@ -97,7 +98,7 @@ read_source(const string &root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_def_scope->define_variable("TREE", _tree.get_complete_subtree());
|
||||
_def_scope->define_variable("TREE", _tree.get_complete_tree());
|
||||
|
||||
if (_tree.count_source_files() == 0) {
|
||||
cerr << "Could not find any source definition files named " << SOURCE_FILENAME
|
||||
@@ -131,7 +132,22 @@ read_source(const string &root) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPMain::
|
||||
process_all() {
|
||||
return r_process_all(&_tree);
|
||||
string cache_filename = _def_scope->expand_variable("DEPENDENCY_CACHE_FILENAME");
|
||||
|
||||
if (cache_filename.empty()) {
|
||||
cerr << "Warning: no definition given for $[DEPENDENCY_CACHE_FILENAME].\n";
|
||||
} else {
|
||||
_tree.read_file_dependencies(cache_filename);
|
||||
}
|
||||
|
||||
if (!r_process_all(_tree.get_root())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cache_filename.empty()) {
|
||||
_tree.update_file_dependencies(cache_filename);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -144,8 +160,8 @@ process_all() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPMain::
|
||||
process(const string &dirname) {
|
||||
PPDirectoryTree *dir = _tree.find_dirname(dirname);
|
||||
if (dir == (PPDirectoryTree *)NULL) {
|
||||
PPDirectory *dir = _tree.find_dirname(dirname);
|
||||
if (dir == (PPDirectory *)NULL) {
|
||||
cerr << "Unknown directory: " << dirname << "\n";
|
||||
return false;
|
||||
}
|
||||
@@ -158,13 +174,47 @@ process(const string &dirname) {
|
||||
return p_process(dir);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPMain::report_depends
|
||||
// Access: Public
|
||||
// Description: Reports all the directories that the named directory
|
||||
// depends on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPMain::
|
||||
report_depends(const string &dirname) const {
|
||||
PPDirectory *dir = _tree.find_dirname(dirname);
|
||||
if (dir == (PPDirectory *)NULL) {
|
||||
cerr << "Unknown directory: " << dirname << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
dir->report_depends();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPMain::report_needs
|
||||
// Access: Public
|
||||
// Description: Reports all the directories that depend on (need) the
|
||||
// named directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPMain::
|
||||
report_needs(const string &dirname) const {
|
||||
PPDirectory *dir = _tree.find_dirname(dirname);
|
||||
if (dir == (PPDirectory *)NULL) {
|
||||
cerr << "Unknown directory: " << dirname << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
dir->report_needs();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPMain::r_process_all
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of process_all().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPMain::
|
||||
r_process_all(PPDirectoryTree *dir) {
|
||||
r_process_all(PPDirectory *dir) {
|
||||
if (dir->get_source() != (PPCommandFile *)NULL) {
|
||||
if (!p_process(dir)) {
|
||||
return false;
|
||||
@@ -187,7 +237,7 @@ r_process_all(PPDirectoryTree *dir) {
|
||||
// Description: The private implementation of process().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPMain::
|
||||
p_process(PPDirectoryTree *dir) {
|
||||
p_process(PPDirectory *dir) {
|
||||
current_output_directory = dir;
|
||||
_named_scopes.set_current(dir->get_dirname());
|
||||
PPCommandFile *source = dir->get_source();
|
||||
|
||||
@@ -29,9 +29,12 @@ public:
|
||||
bool process_all();
|
||||
bool process(const string &dirname);
|
||||
|
||||
void report_depends(const string &dirname) const;
|
||||
void report_needs(const string &dirname) const;
|
||||
|
||||
private:
|
||||
bool r_process_all(PPDirectoryTree *dir);
|
||||
bool p_process(PPDirectoryTree *dir);
|
||||
bool r_process_all(PPDirectory *dir);
|
||||
bool p_process(PPDirectory *dir);
|
||||
bool read_global_file();
|
||||
static string get_cwd();
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "ppNamedScopes.h"
|
||||
#include "ppScope.h"
|
||||
#include "ppDirectoryTree.h"
|
||||
#include "ppDirectory.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
@@ -15,12 +15,12 @@
|
||||
class SortScopesByDependencyAndName {
|
||||
public:
|
||||
bool operator () (const PPScope *a, const PPScope *b) const {
|
||||
PPDirectoryTree *da = a->get_directory();
|
||||
PPDirectoryTree *db = b->get_directory();
|
||||
PPDirectory *da = a->get_directory();
|
||||
PPDirectory *db = b->get_directory();
|
||||
|
||||
// Scopes without associated directories appear first in the list.
|
||||
bool da_is_null = (da == (PPDirectoryTree *)NULL);
|
||||
bool db_is_null = (db == (PPDirectoryTree *)NULL);
|
||||
bool da_is_null = (da == (PPDirectory *)NULL);
|
||||
bool db_is_null = (db == (PPDirectory *)NULL);
|
||||
|
||||
if (da_is_null != db_is_null) {
|
||||
return da_is_null > db_is_null;
|
||||
@@ -33,8 +33,8 @@ public:
|
||||
} else {
|
||||
// Otherwise, both scopes have associated directories, and we
|
||||
// can properly put them in order by dependencies.
|
||||
assert(da != (PPDirectoryTree *)NULL);
|
||||
assert(db != (PPDirectoryTree *)NULL);
|
||||
assert(da != (PPDirectory *)NULL);
|
||||
assert(db != (PPDirectory *)NULL);
|
||||
if (da->get_depends_index() != db->get_depends_index()) {
|
||||
return da->get_depends_index() < db->get_depends_index();
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#include "ppScope.h"
|
||||
#include "ppNamedScopes.h"
|
||||
#include "ppFilenamePattern.h"
|
||||
#include "ppDirectoryTree.h"
|
||||
#include "ppDirectory.h"
|
||||
#include "ppSubroutine.h"
|
||||
#include "ppCommandFile.h"
|
||||
#include "ppDependableFile.h"
|
||||
#include "tokenize.h"
|
||||
#include "find_searchpath.h"
|
||||
|
||||
@@ -23,6 +24,7 @@
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
|
||||
static const string variable_patsubst(VARIABLE_PATSUBST);
|
||||
|
||||
@@ -39,7 +41,7 @@ PPScope::
|
||||
PPScope(PPNamedScopes *named_scopes) :
|
||||
_named_scopes(named_scopes)
|
||||
{
|
||||
_directory = (PPDirectoryTree *)NULL;
|
||||
_directory = (PPDirectory *)NULL;
|
||||
_parent_scope = (PPScope *)NULL;
|
||||
}
|
||||
|
||||
@@ -368,21 +370,21 @@ find_map_variable(const string &varname) const {
|
||||
// scope, if any, or with the nearest parent to this
|
||||
// scope.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPDirectoryTree *PPScope::
|
||||
PPDirectory *PPScope::
|
||||
get_directory() const {
|
||||
if (_directory != (PPDirectoryTree *)NULL) {
|
||||
if (_directory != (PPDirectory *)NULL) {
|
||||
return _directory;
|
||||
}
|
||||
|
||||
// Check the stack.
|
||||
ScopeStack::reverse_iterator si;
|
||||
for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
|
||||
if ((*si)->_directory != (PPDirectoryTree *)NULL) {
|
||||
if ((*si)->_directory != (PPDirectory *)NULL) {
|
||||
return (*si)->_directory;
|
||||
}
|
||||
}
|
||||
|
||||
return (PPDirectoryTree *)NULL;
|
||||
return (PPDirectory *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -394,7 +396,7 @@ get_directory() const {
|
||||
// known directory level.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPScope::
|
||||
set_directory(PPDirectoryTree *directory) {
|
||||
set_directory(PPDirectory *directory) {
|
||||
_directory = directory;
|
||||
}
|
||||
|
||||
@@ -545,6 +547,44 @@ tokenize_params(const string &str, vector<string> &tokens,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::tokenize_numeric_pair
|
||||
// Access: Public
|
||||
// Description: This function is used by all the numeric comparision
|
||||
// functions, e.g. nne, nlt, etc. It splits the string
|
||||
// up into two parameters based on commas, and evaluates
|
||||
// each parameter as a number, into a and b. It returns
|
||||
// true if successful, or false if there was some user
|
||||
// error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPScope::
|
||||
tokenize_numeric_pair(const string &str, double &a, double &b) const {
|
||||
vector<string> words;
|
||||
tokenize_params(str, words, true);
|
||||
if (words.size() != 2) {
|
||||
cerr << words.size() << " parameters supplied when two were expected:\n"
|
||||
<< str << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
double results[2];
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
const char *param = words[i].c_str();
|
||||
char *n;
|
||||
results[i] = strtod(param, &n);
|
||||
if (n == param) {
|
||||
// strtod failed--not a numeric representation.
|
||||
cerr << "Warning: " << words[i] << " is not a number.\n";
|
||||
results[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
a = results[0];
|
||||
b = results[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::p_set_variable
|
||||
// Access: Private
|
||||
@@ -586,8 +626,8 @@ p_get_variable(const string &varname, string &result) const {
|
||||
}
|
||||
|
||||
if (varname == "RELDIR" &&
|
||||
_directory != (PPDirectoryTree *)NULL &&
|
||||
current_output_directory != (PPDirectoryTree *)NULL) {
|
||||
_directory != (PPDirectory *)NULL &&
|
||||
current_output_directory != (PPDirectory *)NULL) {
|
||||
// $[RELDIR] is a special variable name that evaluates to the
|
||||
// relative directory of the current scope to the current output
|
||||
// directory.
|
||||
@@ -596,7 +636,7 @@ p_get_variable(const string &varname, string &result) const {
|
||||
}
|
||||
|
||||
if (varname == "DEPENDS_INDEX" &&
|
||||
_directory != (PPDirectoryTree *)NULL) {
|
||||
_directory != (PPDirectory *)NULL) {
|
||||
// $[DEPENDS_INDEX] is another special variable name that
|
||||
// evaluates to the numeric sorting index assigned to this
|
||||
// directory based on its dependency relationship with other
|
||||
@@ -797,6 +837,18 @@ r_expand_variable(const string &str, size_t &vp,
|
||||
return expand_eq(params);
|
||||
} else if (funcname == "ne") {
|
||||
return expand_ne(params);
|
||||
} else if (funcname == "=" || funcname == "==") {
|
||||
return expand_eqn(params);
|
||||
} else if (funcname == "!=") {
|
||||
return expand_nen(params);
|
||||
} else if (funcname == "<") {
|
||||
return expand_ltn(params);
|
||||
} else if (funcname == "<=") {
|
||||
return expand_len(params);
|
||||
} else if (funcname == ">") {
|
||||
return expand_gtn(params);
|
||||
} else if (funcname == ">=") {
|
||||
return expand_gen(params);
|
||||
} else if (funcname == "not") {
|
||||
return expand_not(params);
|
||||
} else if (funcname == "or") {
|
||||
@@ -813,6 +865,8 @@ r_expand_variable(const string &str, size_t &vp,
|
||||
return expand_closure(params);
|
||||
} else if (funcname == "unmapped") {
|
||||
return expand_unmapped(params);
|
||||
} else if (funcname == "dependencies") {
|
||||
return expand_dependencies(params);
|
||||
}
|
||||
|
||||
// It must be a map variable.
|
||||
@@ -1665,7 +1719,8 @@ expand_if(const string ¶ms) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_eq
|
||||
// Access: Private
|
||||
// Description: Expands the "eq" function variable.
|
||||
// Description: Expands the "eq" function variable. This tests
|
||||
// string equivalence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_eq(const string ¶ms) const {
|
||||
@@ -1689,7 +1744,8 @@ expand_eq(const string ¶ms) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_ne
|
||||
// Access: Private
|
||||
// Description: Expands the "ne" function variable.
|
||||
// Description: Expands the "ne" function variable. This tests
|
||||
// string equivalence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_ne(const string ¶ms) const {
|
||||
@@ -1710,6 +1766,126 @@ expand_ne(const string ¶ms) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_eqn
|
||||
// Access: Private
|
||||
// Description: Expands the "=" function variable. This tests
|
||||
// numeric equivalence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_eqn(const string ¶ms) const {
|
||||
double a, b;
|
||||
if (!tokenize_numeric_pair(params, a, b)) {
|
||||
return string();
|
||||
}
|
||||
|
||||
string result;
|
||||
if (a == b) {
|
||||
result = "1";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_nen
|
||||
// Access: Private
|
||||
// Description: Expands the "!=" function variable. This tests
|
||||
// numeric equivalence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_nen(const string ¶ms) const {
|
||||
double a, b;
|
||||
if (!tokenize_numeric_pair(params, a, b)) {
|
||||
return string();
|
||||
}
|
||||
|
||||
string result;
|
||||
if (a != b) {
|
||||
result = "1";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_ltn
|
||||
// Access: Private
|
||||
// Description: Expands the "<" function variable. This tests
|
||||
// numeric relationships.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_ltn(const string ¶ms) const {
|
||||
double a, b;
|
||||
if (!tokenize_numeric_pair(params, a, b)) {
|
||||
return string();
|
||||
}
|
||||
|
||||
string result;
|
||||
if (a < b) {
|
||||
result = "1";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_len
|
||||
// Access: Private
|
||||
// Description: Expands the "<=" function variable. This tests
|
||||
// numeric relationships.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_len(const string ¶ms) const {
|
||||
double a, b;
|
||||
if (!tokenize_numeric_pair(params, a, b)) {
|
||||
return string();
|
||||
}
|
||||
|
||||
string result;
|
||||
if (a <= b) {
|
||||
result = "1";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_gtn
|
||||
// Access: Private
|
||||
// Description: Expands the ">" function variable. This tests
|
||||
// numeric relationships.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_gtn(const string ¶ms) const {
|
||||
double a, b;
|
||||
if (!tokenize_numeric_pair(params, a, b)) {
|
||||
return string();
|
||||
}
|
||||
|
||||
string result;
|
||||
if (a > b) {
|
||||
result = "1";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_gen
|
||||
// Access: Private
|
||||
// Description: Expands the ">=" function variable. This tests
|
||||
// numeric relationships.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_gen(const string ¶ms) const {
|
||||
double a, b;
|
||||
if (!tokenize_numeric_pair(params, a, b)) {
|
||||
return string();
|
||||
}
|
||||
|
||||
string result;
|
||||
if (a >= b) {
|
||||
result = "1";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_not
|
||||
// Access: Private
|
||||
@@ -1724,7 +1900,7 @@ expand_not(const string ¶ms) const {
|
||||
tokenize_params(params, tokens, true);
|
||||
|
||||
if (tokens.size() != 1) {
|
||||
cerr << "not requires two parameters.\n";
|
||||
cerr << "not requires one parameter.\n";
|
||||
return string();
|
||||
}
|
||||
|
||||
@@ -1778,11 +1954,12 @@ expand_and(const string ¶ms) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens.empty()) {
|
||||
return "1";
|
||||
} else {
|
||||
return tokens.back();
|
||||
string result = "1";
|
||||
if (!tokens.empty()) {
|
||||
result = tokens.back();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -1974,6 +2151,43 @@ expand_unmapped(const string ¶ms) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_dependencies
|
||||
// Access: Private
|
||||
// Description: Expands the "dependencies" function variable. This
|
||||
// function returns all of the inter-file dependencies
|
||||
// that the named file(s) depend on, as defined by the
|
||||
// #include directives appearing within the files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PPScope::
|
||||
expand_dependencies(const string ¶ms) const {
|
||||
// Split the string up into filenames based on whitespace.
|
||||
vector<string> filenames;
|
||||
tokenize_whitespace(expand_string(params), filenames);
|
||||
|
||||
vector<string> results;
|
||||
vector<string>::const_iterator fi;
|
||||
for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
|
||||
PPDependableFile *file = _directory->get_dependable_file(*fi, false);
|
||||
assert(file != (PPDependableFile *)NULL);
|
||||
|
||||
set<PPDependableFile *> files;
|
||||
file->get_complete_dependencies(files);
|
||||
|
||||
set<PPDependableFile *>::const_iterator dfi;
|
||||
for (dfi = files.begin(); dfi != files.end(); ++dfi) {
|
||||
PPDependableFile *df = (*dfi);
|
||||
string rel_filename =
|
||||
current_output_directory->get_rel_to(df->get_directory()) + "/" +
|
||||
df->get_filename();
|
||||
results.push_back(rel_filename);
|
||||
}
|
||||
}
|
||||
|
||||
string result = repaste(results, " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPScope::expand_function
|
||||
// Access: Private
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <vector>
|
||||
|
||||
class PPNamedScopes;
|
||||
class PPDirectoryTree;
|
||||
class PPDirectory;
|
||||
class PPSubroutine;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -47,8 +47,8 @@ public:
|
||||
string expand_variable(const string &varname) const;
|
||||
MapVariableDefinition &find_map_variable(const string &varname) const;
|
||||
|
||||
PPDirectoryTree *get_directory() const;
|
||||
void set_directory(PPDirectoryTree *directory);
|
||||
PPDirectory *get_directory() const;
|
||||
void set_directory(PPDirectory *directory);
|
||||
|
||||
string expand_string(const string &str) const;
|
||||
string expand_self_reference(const string &str, const string &varname) const;
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
|
||||
void tokenize_params(const string &str, vector<string> &tokens,
|
||||
bool expand) const;
|
||||
bool tokenize_numeric_pair(const string &str, double &a, double &b) const;
|
||||
|
||||
static MapVariableDefinition _null_map_def;
|
||||
|
||||
@@ -96,6 +97,12 @@ private:
|
||||
string expand_if(const string ¶ms) const;
|
||||
string expand_eq(const string ¶ms) const;
|
||||
string expand_ne(const string ¶ms) const;
|
||||
string expand_eqn(const string ¶ms) const;
|
||||
string expand_nen(const string ¶ms) const;
|
||||
string expand_ltn(const string ¶ms) const;
|
||||
string expand_len(const string ¶ms) const;
|
||||
string expand_gtn(const string ¶ms) const;
|
||||
string expand_gen(const string ¶ms) const;
|
||||
string expand_not(const string ¶ms) const;
|
||||
string expand_or(const string ¶ms) const;
|
||||
string expand_and(const string ¶ms) const;
|
||||
@@ -104,6 +111,7 @@ private:
|
||||
string expand_cdefine(const string ¶ms) const;
|
||||
string expand_closure(const string ¶ms) const;
|
||||
string expand_unmapped(const string ¶ms) const;
|
||||
string expand_dependencies(const string ¶ms) const;
|
||||
string expand_function(const string &funcname, const PPSubroutine *sub,
|
||||
const string ¶ms) const;
|
||||
string expand_map_variable(const string &varname, const string ¶ms) const;
|
||||
@@ -117,7 +125,7 @@ private:
|
||||
|
||||
PPNamedScopes *_named_scopes;
|
||||
|
||||
PPDirectoryTree *_directory;
|
||||
PPDirectory *_directory;
|
||||
|
||||
typedef map<string, string> Variables;
|
||||
Variables _variables;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "ppremake.h"
|
||||
#include "ppMain.h"
|
||||
#include "ppScope.h"
|
||||
#include "check_include.h"
|
||||
#include "tokenize.h"
|
||||
|
||||
#ifdef HAVE_GETOPT
|
||||
#include <getopt.h>
|
||||
@@ -13,6 +15,12 @@
|
||||
#include <gnu_getopt.h>
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
usage() {
|
||||
cerr <<
|
||||
@@ -20,16 +28,16 @@ usage() {
|
||||
"ppremake [opts] subdir-name [subdir-name..]\n"
|
||||
"ppremake\n"
|
||||
"\n"
|
||||
"This is Panda pre-make: a script preprocessor that scans the directory\n"
|
||||
"hierarchy beginning at root-directory, looking for directories that\n"
|
||||
"contain a file called " SOURCE_FILENAME ". At the top of the directory\n"
|
||||
"tree must be a file called " PACKAGE_FILENAME ", which should define\n"
|
||||
"This is Panda pre-make: a script preprocessor that scans the source\n"
|
||||
"directory hierarchy containing the current directory, looking for\n"
|
||||
"directories that contain a file called " SOURCE_FILENAME ". At the top of the\n"
|
||||
"directory tree must be a file called " PACKAGE_FILENAME ", which should define\n"
|
||||
"key variable definitions for processing, as well as pointing out the\n"
|
||||
"locations of further config files.\n\n"
|
||||
|
||||
"The package file is read and interpreted, followed by each source file\n"
|
||||
"in turn; after each source file is read, the template file (specified in\n"
|
||||
"the config file) is read. The template file contains the actual statements\n"
|
||||
"the config file) is read. The template file contains the actual statements\n"
|
||||
"to be output and will typically be set up to generate Makefiles or whatever\n"
|
||||
"is equivalent and appropriate to the particular build environment in use.\n\n"
|
||||
|
||||
@@ -45,6 +53,16 @@ usage() {
|
||||
" -h Display this page.\n"
|
||||
" -V Report the version of ppremake, and exit.\n"
|
||||
" -P Report the current platform name, and exit.\n\n"
|
||||
" -D pp.dep Examine the given dependency file, and re-run ppremake\n"
|
||||
" only if the dependency file is stale.\n\n"
|
||||
" -d Instead of generating makefiles, report the set of\n"
|
||||
" subdirectories that the named subdirectory depends on.\n"
|
||||
" Directories are named by their local name, not by the\n"
|
||||
" path to them; e.g. util instead of src/util.\n"
|
||||
" -n As above, but report the set of subdirectories that\n"
|
||||
" depend on (need) the named subdirectory. Options -d and\n"
|
||||
" -n may be combined, and you may also name multiple\n"
|
||||
" subdirectories to scan at once.\n\n"
|
||||
" -p platform Build as if for the indicated platform name.\n\n";
|
||||
}
|
||||
|
||||
@@ -58,13 +76,122 @@ report_platform() {
|
||||
cerr << "ppremake built for platform " << PLATFORM << ".\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: check_one_file
|
||||
// Description: Checks a single file listed in the dependency cache
|
||||
// to see if it matches the cache. Returns true if it
|
||||
// does, false if it does not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static bool
|
||||
check_one_file(const string &dir_prefix, const vector<string> &words) {
|
||||
assert(words.size() >= 2);
|
||||
|
||||
string pathname = dir_prefix + words[0];
|
||||
time_t mtime = strtol(words[1].c_str(), (char **)NULL, 10);
|
||||
|
||||
struct stat st;
|
||||
if (stat(pathname.c_str(), &st) < 0) {
|
||||
// The file doesn't even exist!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (st.st_mtime == mtime) {
|
||||
// The modification time matches; don't bother to read the file.
|
||||
return true;
|
||||
}
|
||||
|
||||
// The modification time doesn't match, so we'll need to read the
|
||||
// file and look for #include directives. First, get the complete
|
||||
// set of files we're expecting to find.
|
||||
|
||||
set<string> expected_files;
|
||||
for (int i = 2; i < (int)words.size(); i++) {
|
||||
const string &word = words[i];
|
||||
size_t slash = word.rfind('/');
|
||||
if (slash == string::npos) {
|
||||
// Every file is expected to include a slash.
|
||||
return false;
|
||||
}
|
||||
expected_files.insert(word.substr(slash + 1));
|
||||
}
|
||||
|
||||
// Now open the source file and read it for #include directives.
|
||||
set<string> found_files;
|
||||
ifstream in(pathname.c_str());
|
||||
if (!in) {
|
||||
// Can't read the file for some reason.
|
||||
return false;
|
||||
}
|
||||
|
||||
string line;
|
||||
getline(in, line);
|
||||
while (!in.fail() && !in.eof()) {
|
||||
string filename = check_include(line);
|
||||
if (!filename.empty() && filename.find('/') == string::npos) {
|
||||
found_files.insert(filename);
|
||||
}
|
||||
getline(in, line);
|
||||
}
|
||||
|
||||
// Now check that the two sets are equivalent.
|
||||
return (expected_files == found_files);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: check_dependencies
|
||||
// Description: Read in the indicated dependency cache file,
|
||||
// verifying that it is still current. If it is stale,
|
||||
// return false; otherwise, return true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static bool
|
||||
check_dependencies(const string &dep_filename) {
|
||||
// Extract the directory prefix from the dependency filename. This
|
||||
// is everything up until (and including) the last slash.
|
||||
string dir_prefix;
|
||||
size_t slash = dep_filename.rfind('/');
|
||||
if (slash != string::npos) {
|
||||
dir_prefix = dep_filename.substr(0, slash + 1);
|
||||
}
|
||||
|
||||
ifstream in(dep_filename.c_str());
|
||||
if (!in) {
|
||||
// The dependency filename doesn't even exist: it's definitely
|
||||
// stale.
|
||||
return false;
|
||||
}
|
||||
|
||||
string line;
|
||||
getline(in, line);
|
||||
while (!in.fail() && !in.eof()) {
|
||||
vector<string> words;
|
||||
tokenize_whitespace(line, words);
|
||||
if (words.size() < 2) {
|
||||
// Invalid file; return false.
|
||||
return false;
|
||||
}
|
||||
if (!check_one_file(dir_prefix, words)) {
|
||||
// This file is stale; return false.
|
||||
return false;
|
||||
}
|
||||
getline(in, line);
|
||||
}
|
||||
|
||||
// All files are ok; return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
string progname = argv[0];
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
const char *optstr = "hVPp:";
|
||||
const char *optstr = "hVPD:p:dn";
|
||||
|
||||
bool any_d = false;
|
||||
bool dependencies_stale = false;
|
||||
string platform = PLATFORM;
|
||||
bool report_depends = false;
|
||||
bool report_needs = false;
|
||||
int flag = getopt(argc, argv, optstr);
|
||||
|
||||
while (flag != EOF) {
|
||||
@@ -83,10 +210,25 @@ main(int argc, char *argv[]) {
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (!check_dependencies(optarg)) {
|
||||
dependencies_stale = true;
|
||||
}
|
||||
any_d = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
platform = optarg;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
report_depends = true;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
report_needs = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
@@ -96,26 +238,59 @@ main(int argc, char *argv[]) {
|
||||
argc -= (optind-1);
|
||||
argv += (optind-1);
|
||||
|
||||
// If the user supplied one or more -d parameters, then we should
|
||||
// not continue unless some of the dependencies were stale.
|
||||
if (any_d) {
|
||||
if (!dependencies_stale) {
|
||||
exit(0);
|
||||
}
|
||||
cout << progname << "\n";
|
||||
}
|
||||
|
||||
PPScope global_scope((PPNamedScopes *)NULL);
|
||||
global_scope.define_variable("PROGRAM", PACKAGE);
|
||||
global_scope.define_variable("PROGVER", VERSION);
|
||||
global_scope.define_variable("PPREMAKE", PACKAGE);
|
||||
global_scope.define_variable("PPREMAKE_VERSION", VERSION);
|
||||
global_scope.define_variable("PLATFORM", platform);
|
||||
global_scope.define_variable("PACKAGE_FILENAME", PACKAGE_FILENAME);
|
||||
global_scope.define_variable("SOURCE_FILENAME", SOURCE_FILENAME);
|
||||
|
||||
PPMain ppmain(&global_scope);
|
||||
if (!ppmain.read_source(".")) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
if (!ppmain.process_all()) {
|
||||
if (report_depends || report_needs) {
|
||||
// With -d or -n, just report inter-directory dependency
|
||||
// relationships.
|
||||
if (argc < 2) {
|
||||
cerr << "No named directories.\n";
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!ppmain.process(argv[i])) {
|
||||
cerr << "Unable to process " << argv[i] << ".\n";
|
||||
if (report_depends) {
|
||||
ppmain.report_depends(argv[i]);
|
||||
}
|
||||
if (report_needs) {
|
||||
ppmain.report_needs(argv[i]);
|
||||
}
|
||||
cerr << "\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
// Without -d or -n, do normal processing.
|
||||
|
||||
if (argc < 2) {
|
||||
if (!ppmain.process_all()) {
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!ppmain.process(argv[i])) {
|
||||
cerr << "Unable to process " << argv[i] << ".\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ using namespace std;
|
||||
#define PACKAGE_FILENAME "Package.pp"
|
||||
#define SOURCE_FILENAME "Sources.pp"
|
||||
|
||||
#define DIRECTORY_SEPARATOR '/'
|
||||
#define COMMAND_PREFIX '#'
|
||||
#define VARIABLE_PREFIX '$'
|
||||
#define VARIABLE_OPEN_BRACE '['
|
||||
|
||||
Reference in New Issue
Block a user