| 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 |