3131import shutil
3232import tarfile
3333
34+ # LiveCode build configuration script
35+ import config
36+
3437# The set of platforms for which this branch supports automated builds
3538BUILDBOT_PLATFORMS = ('linux-x86' , 'linux-x86_64' , 'android-armv6' , 'mac' ,
3639 'ios' , 'win-x86' , 'emscripten' )
@@ -77,6 +80,9 @@ def get_buildtype():
7780def get_build_edition ():
7881 return os .environ .get ('BUILD_EDITION' , 'community' )
7982
83+ def get_git_commit ():
84+ return subprocess .check_output (['git' ,'rev-parse' ,'HEAD' ]).strip ()
85+
8086################################################################
8187# Defer to buildbot.mk
8288################################################################
@@ -91,7 +97,6 @@ def exec_buildbot_make(target):
9197################################################################
9298
9399def exec_configure (args ):
94- import config
95100 print ('config.py ' + ' ' .join (args ))
96101 sys .exit (config .configure (args ))
97102
@@ -118,15 +123,69 @@ def exec_make(target):
118123 print (' ' .join (args ))
119124 sys .exit (subprocess .call (args ))
120125
126+ # mspdbsrv is the service used by Visual Studio to collect debug
127+ # data during compilation. One instance is shared by all C++
128+ # compiler instances and threads. It poses a unique challenge in
129+ # several ways:
130+ #
131+ # - If not running when the build job starts, the build job will
132+ # automatically spawn it as soon as it needs to emit debug symbols.
133+ # There's no way to prevent this from happening.
134+ #
135+ # - The build job _doesn't_ automatically clean it up when it finishes
136+ #
137+ # - By default, mspdbsrv inherits its parent process' file handles,
138+ # including (unfortunately) some log handles owned by Buildbot. This
139+ # can prevent Buildbot from detecting that the compile job is finished
140+ #
141+ # - If a compile job starts and detects an instance of mspdbsrv already
142+ # running, by default it will reuse it. So, if you have a compile
143+ # job A running, and start a second job B, job B will use job A's
144+ # instance of mspdbsrv. If you kill mspdbsrv when job A finishes,
145+ # job B will die horribly. To make matters worse, the version of
146+ # mspdbsrv should match the version of Visual Studio being used.
147+ #
148+ # This class works around these problems:
149+ #
150+ # - It sets the _MSPDBSRV_ENDPOINT_ to a value that's probably unique to
151+ # the build, to prevent other builds on the same machine from sharing
152+ # the same mspdbsrv endpoint
153+ #
154+ # - It launches mspdbsrv with _all_ file handles closed, so that it
155+ # can't block the build from being detected as finished.
156+ #
157+ # - It explicitly kills mspdbsrv after the build job has finished.
158+ #
159+ # - It wraps all of this into a context manager, so mspdbsrv gets killed
160+ # even if a Python exception causes a non-local exit.
161+ class UniqueMspdbsrv (object ):
162+ def __enter__ (self ):
163+ os .environ ['_MSPDBSRV_ENDPOINT_' ] = '{}-{}-{}' .format (
164+ get_build_edition (), get_git_commit ()[0 :8 ], get_buildtype ())
165+
166+ mspdbsrv_exe = os .path .join (config .get_program_files_x86 (),
167+ 'Microsoft Visual Studio 10.0\\ Common7\\ IDE\\ mspdbsrv.exe' )
168+ args = [mspdbsrv_exe , '-start' , '-shutdowntime' , '-1' ]
169+ print (' ' .join (args ))
170+ self .proc = subprocess .Popen (args , close_fds = True )
171+ return self
172+
173+ def __exit__ (self , type , value , traceback ):
174+ self .proc .terminate ()
175+ return False
176+
121177def exec_msbuild (platform ):
122178 # Run the make.cmd batch script; it's run using Wine if this is
123179 # not actually a Windows system.
124180 cwd = 'build-' + platform
125181
126182 if _platform .system () == 'Windows' :
127- args = ['cmd' , '/C' , '..\\ make.cmd' ]
128- print (' ' .join (args ))
129- sys .exit (subprocess .call (args , cwd = cwd ))
183+ with UniqueMspdbsrv () as mspdbsrv :
184+ args = ['cmd' , '/C' , '..\\ make.cmd' ]
185+ print (' ' .join (args ))
186+ result = subprocess .call (args , cwd = cwd )
187+
188+ sys .exit (result )
130189
131190 else :
132191 args = ['wine' , 'cmd' , '/K' , '..\\ make.cmd' ]
0 commit comments