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