1# -*- coding: utf-8 -*- 2# Copyright 2010-2018, Google Inc. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: 8# 9# * Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above 12# copyright notice, this list of conditions and the following disclaimer 13# in the documentation and/or other materials provided with the 14# distribution. 15# * Neither the name of Google Inc. nor the names of its 16# contributors may be used to endorse or promote products derived from 17# this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31"""Utilitis for copying dependent files for Windows build.""" 32 33__author__ = "yukawa" 34 35import datetime 36import logging 37import optparse 38import os 39import shutil 40 41from .util import PrintErrorAndExit 42 43def ParseOption(): 44 """Parse command line options.""" 45 parser = optparse.OptionParser() 46 MSG = ' you can use %s as path separator' % os.pathsep 47 parser.add_option('--dll_paths', dest='dll_paths', default='', 48 help='Search paths for DLLs.' + MSG) 49 parser.add_option('--pdb_paths', dest='pdb_paths', default='', 50 help='Search paths for PDB files.' + MSG) 51 parser.add_option('--target_dir', dest='target_dir', default='', 52 help='Deploy target directory.') 53 parser.add_option('--basenames', dest='basenames', default='', 54 help='The basenames of DLL and/or PDB.' + MSG) 55 56 (opts, _) = parser.parse_args() 57 58 return opts 59 60 61def DeployMain(full_filename, src_paths, target_absdir): 62 """Main deployment logic. 63 64 Args: 65 full_filename: A string which represents the filename to be copied. 66 src_paths: A string which represents file search path with delimited by 67 a OS-dependent path separator. 68 target_absdir: A string which represents target directory name. 69 """ 70 if not src_paths: 71 return 72 73 target_file_abspath = os.path.join(target_absdir, full_filename) 74 target_abs_dir = os.path.dirname(target_file_abspath) 75 if not os.path.exists(target_abs_dir): 76 os.makedirs(target_abs_dir) 77 78 def _GetLastModifiedTime(filepath): 79 """Returns the last modified time of a file. 80 81 Args: 82 filepath: A string which represents the filename to be checked. 83 84 Returns: 85 A Datetime object which represents the last modified time of the 86 specified filename. If the file does not exist, returns epoch time. 87 """ 88 if not os.path.isfile(filepath): 89 return datetime.datetime.fromtimestamp(0) 90 return datetime.datetime.fromtimestamp(os.path.getmtime(filepath)) 91 92 target_file_mtime = _GetLastModifiedTime(target_file_abspath) 93 94 for path in src_paths.split(os.pathsep): 95 src = os.path.abspath(os.path.join(path, full_filename)) 96 if not os.path.isfile(src): 97 continue 98 if _GetLastModifiedTime(src) <= target_file_mtime: 99 # Older file found. Ignore. 100 continue 101 print('Copying %s to %s' % (src, target_file_abspath)) 102 shutil.copy2(src, target_file_abspath) 103 break 104 105 106def main(): 107 opts = ParseOption() 108 109 if not opts.basenames: 110 PrintErrorAndExit('--basenames option is mandatory.') 111 112 if not opts.target_dir: 113 PrintErrorAndExit('--target_dir option is mandatory.') 114 115 target_absdir = os.path.abspath(opts.target_dir) 116 for basename in opts.basenames.split(os.pathsep): 117 DeployMain(basename + '.dll', opts.dll_paths, target_absdir) 118 DeployMain(basename + '.pdb', opts.pdb_paths, target_absdir) 119 120 121if __name__ == '__main__': 122 main() 123