thirdparty:waf: New files for waf 1.9.10
[Samba.git] / third_party / waf / waflib / extras / go.py
blob2ba54b8116aa6cd24303e9e0209351872460cfc4
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # Tom Wambold tom5760 gmail.com 2009
4 # Thomas Nagy 2010
6 """
7 Go as a language may look nice, but its toolchain is one of the worse a developer
8 has ever seen. It keeps changing though, and I would like to believe that it will get
9 better eventually, but the crude reality is that this tool and the examples are
10 getting broken every few months.
12 If you have been lured into trying to use Go, you should stick to their Makefiles.
13 """
15 import os, platform
17 from waflib import Utils, Task, TaskGen
18 from waflib.TaskGen import feature, extension, after_method, before_method
19 from waflib.Tools.ccroot import link_task, stlink_task, propagate_uselib_vars, process_use
21 class go(Task.Task):
22 run_str = '${GOC} ${GOCFLAGS} ${CPPPATH_ST:INCPATHS} -o ${TGT} ${SRC}'
24 class gopackage(stlink_task):
25 run_str = '${GOP} grc ${TGT} ${SRC}'
27 class goprogram(link_task):
28 run_str = '${GOL} ${GOLFLAGS} -o ${TGT} ${SRC}'
29 inst_to = '${BINDIR}'
30 chmod = Utils.O755
32 class cgopackage(stlink_task):
33 color = 'YELLOW'
34 inst_to = '${LIBDIR}'
35 ext_in = ['.go']
36 ext_out = ['.a']
38 def run(self):
39 src_dir = self.generator.bld.path
40 source = self.inputs
41 target = self.outputs[0].change_ext('')
43 #print ("--> %s" % self.outputs)
44 #print ('++> %s' % self.outputs[1])
45 bld_dir = self.outputs[1]
46 bld_dir.mkdir()
47 obj_dir = bld_dir.make_node('_obj')
48 obj_dir.mkdir()
50 bld_srcs = []
51 for s in source:
52 # FIXME: it seems gomake/cgo stumbles on filenames like a/b/c.go
53 # -> for the time being replace '/' with '_'...
54 #b = bld_dir.make_node(s.path_from(src_dir))
55 b = bld_dir.make_node(s.path_from(src_dir).replace(os.sep,'_'))
56 b.parent.mkdir()
57 #print ('++> %s' % (s.path_from(src_dir),))
58 try:
59 try:os.remove(b.abspath())
60 except Exception:pass
61 os.symlink(s.abspath(), b.abspath())
62 except Exception:
63 # if no support for symlinks, copy the file from src
64 b.write(s.read())
65 bld_srcs.append(b)
66 #print("--|> [%s]" % b.abspath())
67 b.sig = Utils.h_file(b.abspath())
68 pass
69 #self.set_inputs(bld_srcs)
70 #self.generator.bld.raw_deps[self.uid()] = [self.signature()] + bld_srcs
71 makefile_node = bld_dir.make_node("Makefile")
72 makefile_tmpl = '''\
73 # Copyright 2009 The Go Authors. All rights reserved.
74 # Use of this source code is governed by a BSD-style
75 # license that can be found in the LICENSE file. ---
77 include $(GOROOT)/src/Make.inc
79 TARG=%(target)s
81 GCIMPORTS= %(gcimports)s
83 CGOFILES=\\
84 \t%(source)s
86 CGO_CFLAGS= %(cgo_cflags)s
88 CGO_LDFLAGS= %(cgo_ldflags)s
90 include $(GOROOT)/src/Make.pkg
92 %%: install %%.go
93 $(GC) $*.go
94 $(LD) -o $@ $*.$O
96 ''' % {
97 'gcimports': ' '.join(l for l in self.env['GOCFLAGS']),
98 'cgo_cflags' : ' '.join(l for l in self.env['GOCFLAGS']),
99 'cgo_ldflags': ' '.join(l for l in self.env['GOLFLAGS']),
100 'target': target.path_from(obj_dir),
101 'source': ' '.join([b.path_from(bld_dir) for b in bld_srcs])
103 makefile_node.write(makefile_tmpl)
104 #print ("::makefile: %s"%makefile_node.abspath())
105 cmd = Utils.subst_vars('gomake ${GOMAKE_FLAGS}', self.env).strip()
106 o = self.outputs[0].change_ext('.gomake.log')
107 fout_node = bld_dir.find_or_declare(o.name)
108 fout = open(fout_node.abspath(), 'w')
109 rc = self.generator.bld.exec_command(
110 cmd,
111 stdout=fout,
112 stderr=fout,
113 cwd=bld_dir.abspath(),
115 if rc != 0:
116 import waflib.Logs as msg
117 msg.error('** error running [%s] (cgo-%s)' % (cmd, target))
118 msg.error(fout_node.read())
119 return rc
120 self.generator.bld.read_stlib(
121 target,
122 paths=[obj_dir.abspath(),],
124 tgt = self.outputs[0]
125 if tgt.parent != obj_dir:
126 install_dir = os.path.join('${LIBDIR}',
127 tgt.parent.path_from(obj_dir))
128 else:
129 install_dir = '${LIBDIR}'
130 #print('===> %s (%s)' % (tgt.abspath(), install_dir))
131 self.generator.bld.install_files(
132 install_dir,
133 tgt.abspath(),
134 relative_trick=False,
135 postpone=False,
137 return rc
139 @extension('.go')
140 def compile_go(self, node):
141 #print('*'*80, self.name)
142 if not ('cgopackage' in self.features):
143 return self.create_compiled_task('go', node)
144 #print ('compile_go-cgo...')
145 #bld_dir = node.parent.get_bld()
146 #obj_dir = bld_dir.make_node('_obj')
147 return self.create_task('cgopackage', node, node.change_ext('.a'))
149 @feature('gopackage', 'goprogram', 'cgopackage')
150 @before_method('process_source')
151 def go_compiler_is_foobar(self):
152 if self.env.GONAME == 'gcc':
153 return
154 self.source = self.to_nodes(self.source)
155 src = []
156 go = []
157 for node in self.source:
158 if node.name.endswith('.go'):
159 go.append(node)
160 else:
161 src.append(node)
162 self.source = src
163 if not ('cgopackage' in self.features):
164 #print('--> [%s]... (%s)' % (go[0], getattr(self, 'target', 'N/A')))
165 tsk = self.create_compiled_task('go', go[0])
166 tsk.inputs.extend(go[1:])
167 else:
168 #print ('+++ [%s] +++' % self.target)
169 bld_dir = self.path.get_bld().make_node('cgopackage--%s' % self.target.replace(os.sep,'_'))
170 obj_dir = bld_dir.make_node('_obj')
171 target = obj_dir.make_node(self.target+'.a')
172 tsk = self.create_task('cgopackage', go, [target, bld_dir])
173 self.link_task = tsk
175 @feature('gopackage', 'goprogram', 'cgopackage')
176 @after_method('process_source', 'apply_incpaths',)
177 def go_local_libs(self):
178 names = self.to_list(getattr(self, 'use', []))
179 #print ('== go-local-libs == [%s] == use: %s' % (self.name, names))
180 for name in names:
181 tg = self.bld.get_tgen_by_name(name)
182 if not tg:
183 raise Utils.WafError('no target of name %r necessary for %r in go uselib local' % (name, self))
184 tg.post()
185 #print ("-- tg[%s]: %s" % (self.name,name))
186 lnk_task = getattr(tg, 'link_task', None)
187 if lnk_task:
188 for tsk in self.tasks:
189 if isinstance(tsk, (go, gopackage, cgopackage)):
190 tsk.set_run_after(lnk_task)
191 tsk.dep_nodes.extend(lnk_task.outputs)
192 path = lnk_task.outputs[0].parent.abspath()
193 if isinstance(lnk_task, (go, gopackage)):
194 # handle hierarchical packages
195 path = lnk_task.generator.path.get_bld().abspath()
196 elif isinstance(lnk_task, (cgopackage,)):
197 # handle hierarchical cgopackages
198 cgo_obj_dir = lnk_task.outputs[1].find_or_declare('_obj')
199 path = cgo_obj_dir.abspath()
200 # recursively add parent GOCFLAGS...
201 self.env.append_unique('GOCFLAGS',
202 getattr(lnk_task.env, 'GOCFLAGS',[]))
203 # ditto for GOLFLAGS...
204 self.env.append_unique('GOLFLAGS',
205 getattr(lnk_task.env, 'GOLFLAGS',[]))
206 self.env.append_unique('GOCFLAGS', ['-I%s' % path])
207 self.env.append_unique('GOLFLAGS', ['-L%s' % path])
208 for n in getattr(tg, 'includes_nodes', []):
209 self.env.append_unique('GOCFLAGS', ['-I%s' % n.abspath()])
210 pass
211 pass
213 def configure(conf):
215 def set_def(var, val):
216 if not conf.env[var]:
217 conf.env[var] = val
219 goarch = os.getenv('GOARCH')
220 if goarch == '386':
221 set_def('GO_PLATFORM', 'i386')
222 elif goarch == 'amd64':
223 set_def('GO_PLATFORM', 'x86_64')
224 elif goarch == 'arm':
225 set_def('GO_PLATFORM', 'arm')
226 else:
227 set_def('GO_PLATFORM', platform.machine())
229 if conf.env.GO_PLATFORM == 'x86_64':
230 set_def('GO_COMPILER', '6g')
231 set_def('GO_LINKER', '6l')
232 elif conf.env.GO_PLATFORM in ('i386', 'i486', 'i586', 'i686'):
233 set_def('GO_COMPILER', '8g')
234 set_def('GO_LINKER', '8l')
235 elif conf.env.GO_PLATFORM == 'arm':
236 set_def('GO_COMPILER', '5g')
237 set_def('GO_LINKER', '5l')
238 set_def('GO_EXTENSION', '.5')
240 if not (conf.env.GO_COMPILER or conf.env.GO_LINKER):
241 raise conf.fatal('Unsupported platform ' + platform.machine())
243 set_def('GO_PACK', 'gopack')
244 set_def('gopackage_PATTERN', '%s.a')
245 set_def('CPPPATH_ST', '-I%s')
247 set_def('GOMAKE_FLAGS', ['--quiet'])
248 conf.find_program(conf.env.GO_COMPILER, var='GOC')
249 conf.find_program(conf.env.GO_LINKER, var='GOL')
250 conf.find_program(conf.env.GO_PACK, var='GOP')
252 conf.find_program('cgo', var='CGO')
254 TaskGen.feature('go')(process_use)
255 TaskGen.feature('go')(propagate_uselib_vars)