def virtualize_build_dir(self): # Symlinks don't work on Windows. if self.host_platform == 'windows': return branch_name = util.get_branch_name() if not branch_name: return # TODO(rryan) what other branch name characters aren't allowed in # filenames? branch_name = re.sub('[/<>|"]', '_', branch_name).lower() branch_build_dir = os.path.join(self.get_cache_dir(), branch_name) # Write sconsign.dblite files to branch_build_dir so that the file # signatures are kept separate across branches. sconsign_file = os.path.join(branch_build_dir, 'sconsign.dblite') self.env.SConsignFile(sconsign_file) try: print "os.makedirs", branch_build_dir os.makedirs(branch_build_dir) except: # os.makedirs throws an exception if branch_build_dir already # exists. pass virtual_build_dir = os.path.join(branch_build_dir, self.build_dir) # If build_dir is a symlink, check that it points to virtual_build_dir. if os.path.islink(self.build_dir): # Make sure virtual_build_dir exists. This happens if we are # building for a new branch. try: print "os.makedirs", virtual_build_dir os.makedirs(virtual_build_dir) except: # os.makedirs throws an exception if branch_build_dir already # exists. pass # Get the path build_dir points to. build_dir_path = os.readlink(self.build_dir) # If it does not point to virtual_build_dir then unlink and link it # to virtual_build_dir. if os.path.abspath(build_dir_path) != os.path.abspath(virtual_build_dir): print "os.unlink", self.build_dir os.unlink(self.build_dir) print "os.symlink", virtual_build_dir, self.build_dir os.symlink(virtual_build_dir, self.build_dir) elif os.path.isdir(self.build_dir): # If build_dir is a directory, move it to virtual_build_dir. print "shutil.move", self.build_dir, branch_build_dir shutil.move(self.build_dir, branch_build_dir) print "os.symlink", virtual_build_dir, self.build_dir os.symlink(virtual_build_dir, self.build_dir) else: # Make sure virtual_build_dir exists. This happens if we are # building for a new branch. try: print "os.makedirs", virtual_build_dir os.makedirs(virtual_build_dir) except: # os.makedirs throws an exception if branch_build_dir already # exists. pass print "os.symlink", virtual_build_dir, self.build_dir os.symlink(virtual_build_dir, self.build_dir)
def virtualize_build_dir(self): # WARNING: Do not use SCons self.env.SConsignFile to change the location # of .sconsign.dblite or turn build_dir into a symlink. It will mostly # seem to work fine but eventually cause strange build issues (not # re-building a necessary object file, etc.) and cause instability. # See also: asantoni's warning in get_cache_dir. rryan 6/2013 should_virtualize = int(Script.ARGUMENTS.get('virtualize', 1)) if not should_virtualize: return branch_name = util.get_branch_name() if not branch_name: # happens in case of tarball builds, detached HEADs have # branch_name = '(no branch)' return # TODO(rryan) what other branch name characters aren't allowed in # filenames? branch_name = re.sub('[/<>|"]', '_', branch_name).lower() cache_dir = self.get_cache_dir() branch_build_dir = os.path.join(cache_dir, branch_name) virtual_build_dir = os.path.join(branch_build_dir, self.build_dir) virtual_sconsign_file = os.path.join( branch_build_dir, 'sconsign.dblite') virtual_custom_file = os.path.join(branch_build_dir, 'custom.py') old_branch_build_dir = '' old_virtual_build_dir = '' old_virtual_sconsign_file = '' old_virtual_custom_file = '' # Clean up symlinks from our original method of virtualizing. if os.path.islink(self.build_dir): print "os.unlink", self.build_dir os.unlink(self.build_dir) sconsign_file = '.sconsign.dblite' sconsign_branch_file = '.sconsign.branch' # contains the branch name of last build custom_file = 'cache/custom.py' # contains custom build flags sconsign_branch = '' is_branch_different = True if os.path.isfile(sconsign_branch_file): with open(sconsign_branch_file, 'r') as f: sconsign_branch = f.readline() sconsign_branch = sconsign_branch.strip() # Check if there was a checkout of a different branch since the last # build. is_branch_different = sconsign_branch != branch_name if not is_branch_different: # nothing to do return print "branch has changed", sconsign_branch, "->", branch_name if sconsign_branch: old_branch_build_dir = os.path.join(cache_dir, sconsign_branch) old_virtual_build_dir = os.path.join( old_branch_build_dir, self.build_dir) old_virtual_sconsign_file = os.path.join( old_branch_build_dir, 'sconsign.dblite') old_virtual_custom_file = os.path.join( old_branch_build_dir, 'custom.py') if os.path.isdir(self.build_dir): if os.path.isdir(old_virtual_build_dir): raise Exception('%s already exists. ' 'build virtualization cannot continue. Please ' 'move or delete it.' % old_virtual_build_dir) print "shutil.move", self.build_dir, old_virtual_build_dir # move build dir from last build to cache, named with the old # branch name shutil.move(self.build_dir, old_virtual_build_dir) if os.path.isfile(sconsign_file): print "shutil.move", sconsign_file, old_virtual_sconsign_file # move sconsdign-dblite as well shutil.move(sconsign_file, old_virtual_sconsign_file) if os.path.isfile(custom_file): print "shutil.move", custom_file, old_virtual_custom_file # and move custom.py shutil.move(custom_file, old_virtual_custom_file) # all files are saved now so remove .sconsign.branch file # to avoid a new copy after an exception below os.remove(sconsign_branch_file) # Now there should be no folder self.build_dir or file sconsign_file. if os.path.isdir(branch_build_dir): if os.path.isdir(virtual_build_dir): # found a build_dir in cache from a previous build if os.path.isdir(self.build_dir): raise Exception('%s exists without a .sconsign.branch file so ' 'build virtualization cannot continue. Please ' 'move or delete it.' % self.build_dir) print "shutil.move", virtual_build_dir, self.build_dir shutil.move(virtual_build_dir, self.build_dir) if os.path.isfile(virtual_sconsign_file): if os.path.isfile(sconsign_file): raise Exception('%s exists without a .sconsign.branch file so ' 'build virtualization cannot continue. Please ' 'move or delete it.' % sconsign_file) print "shutil.move", virtual_sconsign_file, sconsign_file shutil.move(virtual_sconsign_file, sconsign_file) if os.path.isfile(virtual_custom_file): if os.path.isfile(custom_file): raise Exception('%s exists without a .sconsign.branch file so ' 'build virtualization cannot continue. Please ' 'move or delete it.' % custom_file) print "shutil.move", virtual_custom_file, custom_file shutil.move(virtual_custom_file, custom_file) else: # no cached build dir found, assume this is a branch from the old branch # if not, no problem because scons will rebuild all changed files in any case # copy the old_virtual_dir back if sconsign_branch: if os.path.isdir(old_virtual_build_dir): if os.path.isdir(self.build_dir): raise Exception('%s exists without a .sconsign.branch file so ' 'build virtualization cannot continue. Please ' 'move or delete it.' % self.build_dir) print "shutil.copytree", old_virtual_build_dir, self.build_dir shutil.copytree(old_virtual_build_dir, self.build_dir) if os.path.isfile(old_virtual_sconsign_file): if os.path.isfile(sconsign_file): raise Exception('%s exists without a .sconsign.branch file so ' 'build virtualization cannot continue. Please ' 'move or delete it.' % sconsign_file) print "shutil.copy", virtual_sconsign_file, sconsign_file shutil.copy(old_virtual_sconsign_file, sconsign_file) if os.path.isfile(old_virtual_custom_file): if os.path.isfile(custom_file): raise Exception('%s exists without a .sconsign.branch file so ' 'build virtualization cannot continue. Please ' 'move or delete it.' % custom_file) print "shutil.copy", virtual_custom_file, custom_file shutil.copy(old_virtual_custom_file, custom_file) # create build dir in cache folder for later move print "os.makedirs", branch_build_dir os.makedirs(branch_build_dir) with open(sconsign_branch_file, 'w+') as f: print 'touch', sconsign_branch_file f.write(branch_name)
def virtualize_build_dir(self): # Symlinks don't work on Windows. if self.host_platform == 'windows': return branch_name = util.get_branch_name() if not branch_name: return # TODO(rryan) what other branch name characters aren't allowed in # filenames? branch_name = re.sub('[/<>|"]', '_', branch_name).lower() branch_build_dir = os.path.join(self.get_cache_dir(), branch_name) # Write sconsign.dblite files to branch_build_dir so that the file # signatures are kept separate across branches. sconsign_file = os.path.join(branch_build_dir, 'sconsign.dblite') self.env.SConsignFile(sconsign_file) try: print "os.makedirs", branch_build_dir os.makedirs(branch_build_dir) except: # os.makedirs throws an exception if branch_build_dir already # exists. pass virtual_build_dir = os.path.join(branch_build_dir, self.build_dir) # If build_dir is a symlink, check that it points to virtual_build_dir. if os.path.islink(self.build_dir): # Make sure virtual_build_dir exists. This happens if we are # building for a new branch. try: print "os.makedirs", virtual_build_dir os.makedirs(virtual_build_dir) except: # os.makedirs throws an exception if branch_build_dir already # exists. pass # Get the path build_dir points to. build_dir_path = os.readlink(self.build_dir) # If it does not point to virtual_build_dir then unlink and link it # to virtual_build_dir. if os.path.abspath(build_dir_path) != os.path.abspath( virtual_build_dir): print "os.unlink", self.build_dir os.unlink(self.build_dir) print "os.symlink", virtual_build_dir, self.build_dir os.symlink(virtual_build_dir, self.build_dir) elif os.path.isdir(self.build_dir): # If build_dir is a directory, move it to virtual_build_dir. print "shutil.move", self.build_dir, branch_build_dir shutil.move(self.build_dir, branch_build_dir) print "os.symlink", virtual_build_dir, self.build_dir os.symlink(virtual_build_dir, self.build_dir) else: # Make sure virtual_build_dir exists. This happens if we are # building for a new branch. try: print "os.makedirs", virtual_build_dir os.makedirs(virtual_build_dir) except: # os.makedirs throws an exception if branch_build_dir already # exists. pass print "os.symlink", virtual_build_dir, self.build_dir os.symlink(virtual_build_dir, self.build_dir)