DistTar Builder
The DistTar builder can build a tarfile with an internal directory structure. It can build plain tar files or gz or bzip compressed archives. You can specify a list of directories and/or files to be included as sources for your Tarfile target. The DISTTAR_EXCLUDEEXTS environment variable allows you to specify any file extensions which should not be included in the tar file. By default this include .o and .so,.dll and a couple of others. The DISTTAR_EXCLUDEDIRS environment variable allows you to specify a list of directories that shouldn't be added, and defaults to 'CVS' and '.svn'. The DISTTAR_EXCLUDERES environment variable allows you to specify a list of regular expressions (provided as strings) which, if matched to a relative pathname (via Python's re.search function), will cause that a file to be excluded.
Save this file as 'disttar.py' and put it in your 'toolpath' directory (as defined in your 'Environment' statement in your SConstruct file).
- Original file by Matthew Nicholson.
- Modifications May 02 2006 by John Pye.
- Further modifications to add 'emitter' functionality, John Pye, May 03 2006.
- Further modifications to change text output during tarfile creation, John Pye, May 04 2006.
- Added DISTTAR_EXCLUDERES feature for file exclusion based on regular expressions, John Pye, 24 Jan 2010.
See also the AccumulateBuilder for another approach to this problem.
1 # DistTarBuilder: tool to generate tar files using SCons
2 # Copyright (C) 2005, 2006 Matthew A. Nicholson
3 # Copyright (C) 2006-2010 John Pye
4 #
5 # This file is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License version 2.1 as published by the Free Software Foundation.
8 #
9 # This file is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #
18
19 import os,sys
20 from SCons.Script import *
21 import re
22
23 def disttar_emitter(target,source,env):
24
25 source,origsource = [], source
26
27 excludeexts = env.Dictionary().get('DISTTAR_EXCLUDEEXTS',[])
28 excludedirs = env.Dictionary().get('DISTTAR_EXCLUDEDIRS',[])
29 re1 = env.Dictionary().get('DISTTAR_EXCLUDERES',[])
30 excluderes = [re.compile(r) for r in re1]
31
32 # assume the sources are directories... need to check that
33 for item in origsource:
34 for root, dirs, files in os.walk(str(item)):
35
36 # don't make directory dependences as that triggers full build
37 # of that directory
38 if root in source:
39 #print "Removing directory %s" % root
40 source.remove(root)
41
42 # loop through files in a directory
43 for name in files:
44 ext = os.path.splitext(name)
45 if not ext[1] in excludeexts:
46 relpath = os.path.join(root,name)
47 failre = False
48 for r in excluderes:
49 #print "Match( %s against %s)" % (r,relpath)
50 if r.search(relpath):
51 failre = True
52 #print "Excluding '%s' from tarball" % relpath
53 break
54 if not failre:
55 #print "Adding source",relpath
56 source.append(relpath)
57 for d in excludedirs:
58 if d in dirs:
59 dirs.remove(d) # don't visit CVS directories etc
60
61 return target, source
62
63 def disttar_string(target, source, env):
64 """This is what gets printed on the console. We'll strip out the list
65 or source files, since it tends to get very long. If you want to see the
66 contents, the easiest way is to uncomment the line 'Adding to TAR file'
67 below. """
68 return 'DistTar(%s,...)' % target[0]
69
70 def disttar(target, source, env):
71 """tar archive builder"""
72
73 import tarfile
74
75 env_dict = env.Dictionary()
76
77 if env_dict.get("DISTTAR_FORMAT") in ["gz", "bz2"]:
78 tar_format = env_dict["DISTTAR_FORMAT"]
79 else:
80 tar_format = ""
81
82 # split the target directory, filename, and stuffix
83 base_name = str(target[0]).split('.tar')[0]
84 (target_dir, dir_name) = os.path.split(base_name)
85
86 # create the target directory if it does not exist
87 if target_dir and not os.path.exists(target_dir):
88 os.makedirs(target_dir)
89
90 # open our tar file for writing
91 sys.stderr.write("DistTar: Writing "+str(target[0]))
92 tar = tarfile.open(str(target[0]), "w:%s" % tar_format)
93
94 # write sources to our tar file
95 for item in source:
96 item = str(item)
97 sys.stderr.write(".")
98 #print "Adding to TAR file: %s/%s" % (dir_name,item)
99 tar.add(item,'%s/%s' % (dir_name,item))
100
101 # all done
102 sys.stderr.write("\n") #print "Closing TAR file"
103 tar.close()
104
105 def disttar_suffix(env, sources):
106 """tar archive suffix generator"""
107
108 env_dict = env.Dictionary()
109 if env_dict.has_key("DISTTAR_FORMAT") and env_dict["DISTTAR_FORMAT"] in ["gz", "bz2"]:
110 return ".tar." + env_dict["DISTTAR_FORMAT"]
111 else:
112 return ".tar"
113
114 def generate(env):
115 """
116 Add builders and construction variables for the DistTar builder.
117 """
118
119 disttar_action=SCons.Action.Action(disttar, disttar_string)
120 env['BUILDERS']['DistTar'] = Builder(
121 action=disttar_action
122 , emitter=disttar_emitter
123 , suffix = disttar_suffix
124 , target_factory = env.fs.Entry
125 )
126
127 env.AppendUnique(
128 DISTTAR_FORMAT = 'gz'
129 )
130
131 def exists(env):
132 """
133 Make sure this tool exists.
134 """
135 try:
136 import os
137 import tarfile
138 except ImportError:
139 return False
140 else:
141 return True
142
143 # vim:set ts=4 sw=4 noexpandtab:
Usage
1 #scons buildfile
2
3 # the disttar.py file needs to be in toolpath
4 env = Environment(tools = ["default", "disttar"], toolpath = '.')
5 env.DistTar("dist/archive", ["README", "INSTALL", env.Dir("src")])
6
7 # This will build an archive using what ever DISTTAR_FORMAT that is set.
8 # In this case this will come out to be dist/archive.tar.gz, and all
9 # included files will be in the 'archive' directory within the tar archive.
Another example:
1 env['DISTTAR_FORMAT']='bz2'
2 env.Append(
3 DISTTAR_EXCLUDEEXTS=['.o','.os','.so','.a','.dll','.cc','.cache','.pyc','.cvsignore','.dblite','.log', '.gz', '.bz2', '.zip']
4 , DISTTAR_EXCLUDEDIRS=['CVS','.svn','.sconf_temp', 'dist']
5 , DISTTAR_EXCLUDERES=[r'_wrap\.c$', r'python/swigwrapper\.py$']
6 )
7
8 tar = env.DistTar("dist/ascend-"+version
9 , [env.Dir('#')]
10 )
