OLD | NEW |
| (Empty) |
1 # Copyright 2009, Google Inc. | |
2 # All rights reserved. | |
3 # | |
4 # Redistribution and use in source and binary forms, with or without | |
5 # modification, are permitted provided that the following conditions are | |
6 # met: | |
7 # | |
8 # * Redistributions of source code must retain the above copyright | |
9 # notice, this list of conditions and the following disclaimer. | |
10 # * Redistributions in binary form must reproduce the above | |
11 # copyright notice, this list of conditions and the following disclaimer | |
12 # in the documentation and/or other materials provided with the | |
13 # distribution. | |
14 # * Neither the name of Google Inc. nor the names of its | |
15 # contributors may be used to endorse or promote products derived from | |
16 # this software without specific prior written permission. | |
17 # | |
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | |
30 import os | |
31 import subprocess | |
32 import SCons | |
33 | |
34 Import('env') | |
35 | |
36 # Check if Debian packaging tools are installed. If so, make a .deb package. | |
37 if subprocess.Popen(["which", "dpkg-buildpackage"], | |
38 stdout=open(os.devnull, "w")).wait() == 0: | |
39 | |
40 print('Found dpkg-buildpackage in PATH; will create Debian packages.'); | |
41 | |
42 current_source_dir = os.path.join(env['SCONSTRUCT_DIR'], 'installer/linux') | |
43 | |
44 def OutputFromShellCommand(command): | |
45 process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) | |
46 return process.communicate()[0].strip() | |
47 | |
48 def _InternalBuildDebianPackage(env, src_dir, obj_dir, debian_files, | |
49 package_files, output_dir=None, force_version=None): | |
50 """Creates build rules to build a Debian package from the specified sources. | |
51 | |
52 Args: | |
53 env: SCons Environment. | |
54 src_dir: Current source path, to which the debian_files are | |
55 relative. | |
56 obj_dir: Directory to place object files in. | |
57 debian_files: Array of the Debian control file sources that should be | |
58 copied into the package source tree, e.g., changelog, control, rules, | |
59 etc. Must be relative to current source dir. | |
60 package_files: An array of 2-tuples listing the files that should be | |
61 copied into the package source tree. | |
62 The first element is the path where the file should be placed for the | |
63 .install control file to find it, relative to the generated debian | |
64 package source directory. | |
65 The second element is the file source. | |
66 output_dir: An optional directory to place the files in. If omitted, the | |
67 current output directory is used. | |
68 force_version: Optional. Forces the version of the package to start with | |
69 this version string if specified. If the last entry in the changelog | |
70 is not for a version that starts with this then a dummy entry is | |
71 generated with this version and a ~prerelease suffix (so that the | |
72 final version will compare as greater). | |
73 | |
74 Return: | |
75 A list of the targets (at least two). | |
76 """ | |
77 # Read the control file and changelog file to determine the package name, | |
78 # version, and arch that the Debian build tools will use to name the | |
79 # generated files. | |
80 control_file = None | |
81 changelog_file = None | |
82 for file in debian_files: | |
83 if os.path.basename(file) == "control": | |
84 control_file = os.path.join(src_dir, file) | |
85 elif os.path.basename(file) == "changelog": | |
86 changelog_file = os.path.join(src_dir, file) | |
87 if control_file == None: | |
88 raise Exception("Need to have a control file") | |
89 if changelog_file == None: | |
90 raise Exception("Need to have a changelog file") | |
91 source = OutputFromShellCommand( | |
92 "awk '/^Source:/ { print $2; }' " + control_file) | |
93 packages = OutputFromShellCommand( | |
94 "awk '/^Package:/ { print $2; }' " + control_file).split("\n") | |
95 version = OutputFromShellCommand( | |
96 "sed -nr '1 { s/.*\\((.*)\\).*/\\1/; p }' " + changelog_file) | |
97 arch = OutputFromShellCommand( | |
98 "awk '/^Architecture:/ { print $2; }' %s | head -n 1" % control_file) | |
99 add_dummy_changelog_entry = False | |
100 if force_version != None and not version.startswith(force_version): | |
101 print('Warning: no entry in ' + changelog_file + ' for version ' + | |
102 force_version + ' (last is ' + version +'). A dummy entry will be ' + | |
103 'generated. Remember to add the real changelog entry before ' + | |
104 'releasing.'); | |
105 version = force_version + '~prerelease' | |
106 add_dummy_changelog_entry = True | |
107 source_dir_name = source + "_" + version + "_" + arch | |
108 target_file_names = [ source_dir_name + ".changes" ] | |
109 for package in packages: | |
110 package_file_name = package + "_" + version + "_" + arch + ".deb" | |
111 target_file_names.append(package_file_name) | |
112 # The targets | |
113 if output_dir != None: | |
114 targets = [os.path.join(output_dir, s) for s in target_file_names] | |
115 else: | |
116 targets = target_file_names | |
117 # Path to where we will construct the debian build tree. | |
118 deb_build_tree = os.path.join(obj_dir, source_dir_name, "deb_build_tree") | |
119 # First copy the files. | |
120 for file in package_files: | |
121 env.Command(os.path.join(deb_build_tree, file[0]), file[1], | |
122 SCons.Defaults.Copy('$TARGET', '$SOURCE')) | |
123 env.Depends(targets, os.path.join(deb_build_tree, file[0])) | |
124 # Now copy the Debian metadata sources. We have to do this all at once so | |
125 # that we can remove the target directory before copying, because there | |
126 # can't be any other stale files there or else dpkg-buildpackage may use | |
127 # them and give incorrect build output. | |
128 copied_debian_files_paths = [] | |
129 for file in debian_files: | |
130 copied_debian_files_paths.append(os.path.join(deb_build_tree, "debian", | |
131 os.path.basename(file))) | |
132 copy_commands = [ | |
133 """dir=$$(dirname $TARGET) && \ | |
134 rm -Rf $$dir && \ | |
135 mkdir -p $$dir && \ | |
136 cp $SOURCES $$dir && \ | |
137 chmod -R u+w $$dir""" | |
138 ] | |
139 if add_dummy_changelog_entry: | |
140 copy_commands += [ | |
141 """debchange -c $$(dirname $TARGET)/changelog --newversion %s \ | |
142 --distribution UNRELEASED \ | |
143 'Developer preview build. (This entry was auto-generated.)'""" % | |
144 version | |
145 ] | |
146 env.Command(copied_debian_files_paths, debian_files, copy_commands) | |
147 env.Depends(targets, copied_debian_files_paths) | |
148 # TODO(tschmelcher): Change this to sign the package for Google builds once | |
149 # we start putting out Linux releases. | |
150 # Must explicitly specify -a because otherwise cross-builds won't work. | |
151 # Must explicitly specify -D because -a disables it. | |
152 # Must explicitly specify fakeroot because old dpkg tools don't assume that. | |
153 env.Command(targets, None, | |
154 """dir=%(dir)s && \ | |
155 cd $$dir && \ | |
156 dpkg-buildpackage -b -uc -a%(arch)s -D -rfakeroot && \ | |
157 cd $$OLDPWD && \ | |
158 for file in %(targets)s; do \ | |
159 mv $$dir/../$$file $$(dirname $TARGET); \ | |
160 done""" % | |
161 {'dir':env.Dir(deb_build_tree).path, | |
162 'arch':arch, | |
163 'targets':" ".join(target_file_names)}) | |
164 return targets | |
165 | |
166 def BuildDebianPackage(debian_files, package_files, output_dir=None, | |
167 force_version=None): | |
168 return _InternalBuildDebianPackage(env, current_source_dir, ".", | |
169 debian_files, package_files, output_dir, force_version) | |
170 | |
171 # Build amd64 package. | |
172 BuildDebianPackage(["debian_common/changelog", | |
173 "debian_amd64/control", | |
174 "debian_amd64/google-o3d.install", | |
175 "debian_common/links", | |
176 "debian_amd64/postinst", | |
177 "debian_amd64/prerm", | |
178 "debian_amd64/rules" | |
179 ], | |
180 [("libnpo3dautoplugin.so", | |
181 '$ARTIFACTS_DIR/libnpo3dautoplugin.so'), | |
182 ("libGLEW.so.1.5", '$ARTIFACTS_DIR/libGLEW.so.1.5'), | |
183 ("libCg.so", '$ARTIFACTS_DIR/libCg.so'), | |
184 ("libCgGL.so", '$ARTIFACTS_DIR/libCgGL.so') | |
185 ], | |
186 output_dir='$ARTIFACTS_DIR', | |
187 force_version=env.get('O3D_PLUGIN_VERSION')) | |
188 | |
189 # Build i386 package. | |
190 BuildDebianPackage(["debian_common/changelog", | |
191 "debian_i386/control", | |
192 "debian_i386/google-o3d.install", | |
193 "debian_common/links", | |
194 "debian_i386/rules" | |
195 ], | |
196 [("libnpo3dautoplugin.so", | |
197 '$ARTIFACTS_DIR/libnpo3dautoplugin.so'), | |
198 ("libCg.so", '$ARTIFACTS_DIR/libCg.so'), | |
199 ("libCgGL.so", '$ARTIFACTS_DIR/libCgGL.so') | |
200 ], | |
201 output_dir='$ARTIFACTS_DIR', | |
202 force_version=env.get('O3D_PLUGIN_VERSION')) | |
203 | |
204 else: | |
205 print('dpkg-buildpackage not found in PATH; Debian packages will not be ' | |
206 'built.'); | |
207 | |
208 # TODO(tschmelcher): Also build an RPM and a tgz. | |
OLD | NEW |