1 # Copyright (C) 2006, Thomas Leonard
2 # See http://0install.net/0compile.html
4 import sys
, os
, __main__
, time
5 from os
.path
import join
6 from logging
import info
7 from xml
.dom
import minidom
12 info('Setting %s="%s"', name
, value
)
13 os
.environ
[name
] = value
15 def do_env_binding(binding
, path
):
16 os
.environ
[binding
.name
] = binding
.get_value(path
,
17 os
.environ
.get(binding
.name
, None))
18 info("%s=%s", binding
.name
, os
.environ
[binding
.name
])
20 def do_build_internal(args
):
22 import getpass
, socket
, time
26 builddir
= os
.path
.realpath('build')
27 ensure_dir(buildenv
.metadir
)
29 # Create build-environment.xml file
30 root
= buildenv
.doc
.documentElement
31 info
= buildenv
.doc
.createElementNS(XMLNS_0COMPILE
, 'build-info')
32 root
.appendChild(buildenv
.doc
.createTextNode(' '))
33 root
.appendChild(info
)
34 root
.appendChild(buildenv
.doc
.createTextNode('\n'))
35 info
.setAttributeNS(None, 'time', time
.strftime('%Y-%m-%d %H:%M').strip())
36 info
.setAttributeNS(None, 'host', socket
.getfqdn())
37 info
.setAttributeNS(None, 'user', getpass
.getuser())
39 info
.setAttributeNS(None, 'arch', '%s-%s' % (uname
[0], uname
[4]))
40 buildenv
.doc
.writexml(file(join(buildenv
.metadir
, 'build-environment.xml'), 'w'))
42 # Create local binary interface file
43 src_iface
= iface_cache
.get_interface(buildenv
.interface
)
44 write_sample_interface(src_iface
, buildenv
.local_iface_file
,
45 buildenv
.chosen_impl(buildenv
.interface
))
48 orig_impl
= buildenv
.chosen_impl(buildenv
.interface
)
49 patch_file
= join(buildenv
.distdir
, '0install/from-%s.patch' % orig_impl
.get_version())
50 if os
.path
.isdir('src'):
51 orig_src
= lookup(orig_impl
.id)
52 # (ignore errors; will already be shown on stderr)
53 os
.system("diff -urN '%s' src > %s" %
54 (orig_src
.replace('\\', '\\\\').replace("'", "\\'"),
56 if os
.path
.getsize(patch_file
) == 0:
58 elif os
.path
.exists(patch_file
):
61 env('BUILDDIR', builddir
)
62 env('DISTDIR', buildenv
.distdir
)
63 env('SRCDIR', buildenv
.srcdir
)
66 for needed_iface
in buildenv
.interfaces
:
67 impl
= buildenv
.chosen_impl(needed_iface
)
69 for dep
in impl
.dependencies
.values():
70 dep_iface
= buildenv
.interfaces
[dep
.interface
]
71 for b
in dep
.bindings
:
72 if isinstance(b
, EnvironmentBinding
):
73 dep_impl
= buildenv
.chosen_impl(dep
.interface
)
74 do_env_binding(b
, lookup(dep_impl
.id))
76 if args
== ['--shell']:
77 spawn_and_check(find_in_path('sh'), [])
79 command
= buildenv
.root_impl
.metadata
['command']
80 print "Executing: " + command
84 """build [ --nosandbox ] [ shell ]"""
87 builddir
= os
.path
.realpath('build')
90 ensure_dir(buildenv
.distdir
)
92 if args
[:1] == ['--nosandbox']:
93 return do_build_internal(args
[1:])
95 tmpdir
= tempfile
.mkdtemp(prefix
= '0compile-')
97 my_dir
= os
.path
.dirname(__file__
)
98 readable
= ['.', my_dir
]
99 writable
= ['build', buildenv
.distdir
, tmpdir
]
100 env('TMPDIR', tmpdir
)
101 env('PATH', join(my_dir
, 'bin') + ':' + os
.environ
['PATH'])
103 readable
.append(get_cached_iface_path(buildenv
.interface
))
105 for iface
in buildenv
.interfaces
:
106 readable
.append(lookup(buildenv
.chosen_impl(iface
).id))
109 if __main__
.options
.verbose
:
110 options
.append('--verbose')
111 spawn_maybe_sandboxed(readable
, writable
, tmpdir
, sys
.executable
, [sys
.argv
[0]] + options
+ ['build', '--nosandbox'] + args
)
113 info("Deleting temporary directory '%s'" % tmpdir
)
114 shutil
.rmtree(tmpdir
)
116 def write_sample_interface(iface
, path
, src_impl
):
117 impl
= minidom
.getDOMImplementation()
119 XMLNS_IFACE
= namespaces
.XMLNS_IFACE
121 doc
= impl
.createDocument(XMLNS_IFACE
, "interface", None)
123 root
= doc
.documentElement
124 root
.setAttributeNS(XMLNS_NAMESPACE
, 'xmlns', XMLNS_IFACE
)
126 def addSimple(parent
, name
, text
= None):
127 elem
= doc
.createElementNS(XMLNS_IFACE
, name
)
129 parent
.appendChild(doc
.createTextNode('\n' + ' ' * (1 + depth(parent
))))
130 parent
.appendChild(elem
)
132 elem
.appendChild(doc
.createTextNode(text
))
136 element
.appendChild(doc
.createTextNode('\n' + ' ' * depth(element
)))
138 addSimple(root
, 'name', iface
.name
)
139 addSimple(root
, 'summary', iface
.summary
)
140 addSimple(root
, 'description', iface
.description
)
141 feed_for
= addSimple(root
, 'feed-for')
142 feed_for
.setAttributeNS(None, 'interface', iface
.uri
)
144 group
= addSimple(root
, 'group')
145 main
= src_impl
.metadata
.get('binary-main')
147 group
.setAttributeNS(None, 'main', main
)
150 target_os
, target_machine
= uname
[0], uname
[-1]
151 if target_machine
in ('i585', 'i686'):
152 target_machine
= 'i486' # (sensible default)
154 group
.setAttributeNS(None, 'arch', '%s-%s' % (target_os
, target_machine
))
155 impl_elem
= addSimple(group
, 'implementation')
156 impl_elem
.setAttributeNS(None, 'version', src_impl
.get_version())
157 impl_elem
.setAttributeNS(None, 'id', '..')
158 impl_elem
.setAttributeNS(None, 'released', time
.strftime('%Y-%m-%d'))
162 doc
.writexml(file(path
, 'w'))
164 __main__
.commands
.append(do_build
)