| 1 | #!/usr/bin/env python | 
|---|
| 2 | # | 
|---|
| 3 | # Copyright (c) 2012 Martin Decky | 
|---|
| 4 | # All rights reserved. | 
|---|
| 5 | # | 
|---|
| 6 | # Redistribution and use in source and binary forms, with or without | 
|---|
| 7 | # modification, are permitted provided that the following conditions | 
|---|
| 8 | # are met: | 
|---|
| 9 | # | 
|---|
| 10 | # - Redistributions of source code must retain the above copyright | 
|---|
| 11 | #   notice, this list of conditions and the following disclaimer. | 
|---|
| 12 | # - Redistributions in binary form must reproduce the above copyright | 
|---|
| 13 | #   notice, this list of conditions and the following disclaimer in the | 
|---|
| 14 | #   documentation and/or other materials provided with the distribution. | 
|---|
| 15 | # - The name of the author may not be used to endorse or promote products | 
|---|
| 16 | #   derived from this software without specific prior written permission. | 
|---|
| 17 | # | 
|---|
| 18 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 
|---|
| 19 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
|---|
| 20 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
|---|
| 21 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
|---|
| 22 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
|---|
| 23 | # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|---|
| 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|---|
| 25 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|---|
| 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
|---|
| 27 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|---|
| 28 | # | 
|---|
| 29 |  | 
|---|
| 30 | """ | 
|---|
| 31 | HelenOS out-of-source-tree build utility | 
|---|
| 32 | """ | 
|---|
| 33 |  | 
|---|
| 34 | import sys | 
|---|
| 35 | import os | 
|---|
| 36 | import stat | 
|---|
| 37 | import errno | 
|---|
| 38 | import subprocess | 
|---|
| 39 |  | 
|---|
| 40 | exclude_names = set(['.svn', '.bzr']) | 
|---|
| 41 |  | 
|---|
| 42 | def duplicate_tree(src_path, dest_path, current): | 
|---|
| 43 | "Duplicate source directory tree in the destination path" | 
|---|
| 44 |  | 
|---|
| 45 | for name in os.listdir(os.path.join(src_path, current)): | 
|---|
| 46 | if name in exclude_names: | 
|---|
| 47 | next | 
|---|
| 48 |  | 
|---|
| 49 | following = os.path.join(current, name) | 
|---|
| 50 | src = os.path.join(src_path, following) | 
|---|
| 51 | dest = os.path.join(dest_path, following) | 
|---|
| 52 | dest_parent = os.path.join(dest_path, current) | 
|---|
| 53 | dest_stat = os.stat(src) | 
|---|
| 54 |  | 
|---|
| 55 | # Create shadow directories | 
|---|
| 56 | if stat.S_ISDIR(dest_stat.st_mode): | 
|---|
| 57 | if not os.path.exists(dest): | 
|---|
| 58 | os.mkdir(dest) | 
|---|
| 59 |  | 
|---|
| 60 | if not os.path.isdir(dest): | 
|---|
| 61 | raise IOError(errno.ENOTDIR, "Destination path exists, but is not a directory", dest) | 
|---|
| 62 |  | 
|---|
| 63 | duplicate_tree(src_path, dest_path, following) | 
|---|
| 64 | else: | 
|---|
| 65 | # Compute the relative path from destination to source | 
|---|
| 66 | relative = os.path.relpath(src, dest_parent) | 
|---|
| 67 |  | 
|---|
| 68 | # Create symlink | 
|---|
| 69 | if not os.path.exists(dest): | 
|---|
| 70 | os.symlink(relative, dest) | 
|---|
| 71 |  | 
|---|
| 72 | def usage(prname): | 
|---|
| 73 | "Print usage syntax" | 
|---|
| 74 | print(prname + " <SRC_PATH> <DEST_PATH> [MAKE ARGS...]") | 
|---|
| 75 |  | 
|---|
| 76 | def main(): | 
|---|
| 77 | if len(sys.argv) < 3: | 
|---|
| 78 | usage(sys.argv[0]) | 
|---|
| 79 | return 1 | 
|---|
| 80 |  | 
|---|
| 81 | # Source tree path | 
|---|
| 82 | src_path = os.path.abspath(sys.argv[1]) | 
|---|
| 83 | if not os.path.isdir(src_path): | 
|---|
| 84 | print("<SRC_PATH> must be a directory") | 
|---|
| 85 | return 2 | 
|---|
| 86 |  | 
|---|
| 87 | # Destination tree path | 
|---|
| 88 | dest_path = os.path.abspath(sys.argv[2]) | 
|---|
| 89 | if not os.path.exists(dest_path): | 
|---|
| 90 | os.mkdir(dest_path) | 
|---|
| 91 |  | 
|---|
| 92 | if not os.path.isdir(dest_path): | 
|---|
| 93 | print("<DEST_PATH> must be a directory") | 
|---|
| 94 | return 3 | 
|---|
| 95 |  | 
|---|
| 96 | # Duplicate source directory tree | 
|---|
| 97 | duplicate_tree(src_path, dest_path, "") | 
|---|
| 98 |  | 
|---|
| 99 | # Run the build from the destination tree | 
|---|
| 100 | os.chdir(dest_path) | 
|---|
| 101 | args = ["make"] | 
|---|
| 102 | args.extend(sys.argv[3:]) | 
|---|
| 103 |  | 
|---|
| 104 | return subprocess.Popen(args).wait() | 
|---|
| 105 |  | 
|---|
| 106 | if __name__ == '__main__': | 
|---|
| 107 | sys.exit(main()) | 
|---|