Skip to content

Commit

Permalink
Windows: Script for generating a Visual Studio solution
Browse files Browse the repository at this point in the history
"build\win32\qmake_msvc.py" is a script that generates a full Visual Studio
solution with a .vcxproj for each subproject. It depends on envconfig.bat.
The solution is always placed in a folder called "doomsday-msvc-build" at
the repository root.

qmake_msvc.py must be called whenever the .pro/.pri files change. The .sln
and .vcxproj files are then rewritten -- manual edits will be gone!

The solution automatically deploys all built binaries into the
"distrib\products" folder. The user is expected to 1) copy the required
dependency .dlls to products\bin, and 2) define the appropriate launch
command line and options (which are persistently then stored in the
.vcxproj.user file).
  • Loading branch information
skyjake committed Jan 18, 2013
1 parent 21efaaa commit af74de2
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 0 deletions.
64 changes: 64 additions & 0 deletions doomsday/build/win32/copy_to_products.py
@@ -0,0 +1,64 @@
# Copies all updated binaries to the distrib/products folder.
# Called from Visual Studio as a post-build step for all projects.

import sys, os, shutil

solDir = sys.argv[1]
buildType = sys.argv[2]


def copy_if_newer(src, dest):
if os.path.exists(dest):
srcTime = os.stat(src).st_mtime
destTime = os.stat(dest).st_mtime
if srcTime <= destTime: return
try:
shutil.copyfile(src, dest)
print 'DEPLOY :', os.path.basename(src), '->', os.path.abspath(dest)
except IOError:
pass


# Set up the destination.
dest = os.path.abspath(os.path.join(solDir, '..', 'distrib', 'products', 'bin'))
if not os.path.exists(dest): os.makedirs(dest)
if not os.path.exists(dest + '\\plugins'): os.makedirs(dest + '\\plugins')
if not os.path.exists(dest + '\\..\\data'): os.makedirs(dest + '\\..\\data')

# Update .pk3s.
copy_if_newer(os.path.join(solDir, 'doomsday.pk3'), os.path.join(dest, '..', 'data', 'doomsday.pk3'))
copy_if_newer(os.path.join(solDir, 'libdoom.pk3'), os.path.join(dest, '..', 'data', 'jdoom', 'libdoom.pk3'))
copy_if_newer(os.path.join(solDir, 'libheretic.pk3'), os.path.join(dest, '..', 'data', 'jheretic', 'libdoom.pk3'))
copy_if_newer(os.path.join(solDir, 'libhexen.pk3'), os.path.join(dest, '..', 'data', 'jhexen', 'libhexen.pk3'))
copy_if_newer(os.path.join(solDir, 'libdoom64.pk3'), os.path.join(dest, '..', 'data', 'jdoom64', 'libdoom64.pk3'))

targets = ['libdeng2', 'libdeng1',
'client', 'server',
'plugins\*', 'tools\*', 'tools\shell\*', 'tests\*']

for target in targets:
dirs = []
if '*' in target:
try:
dirs += [target[:-1] + d + '\\' + buildType for d in os.listdir(os.path.join(solDir, target[:-1]))]
except:
pass
else:
dirs += [target + '\\' + buildType]

for dir in dirs:
d = os.path.join(solDir, dir)
if not os.path.exists(d): continue

for fn in os.listdir(d):
if fn[-4:] == '.exe':
#print '- exe:', fn
copy_if_newer(os.path.join(d, fn), os.path.join(dest, fn))
elif fn[-4:] == '.dll':
destPath = dest
if 'plugins' in dir:
#print '- plugin dll:', fn
destPath += '\\plugins'
#else:
# print '- dll:', fn
copy_if_newer(os.path.join(d, fn), os.path.join(destPath, fn))
111 changes: 111 additions & 0 deletions doomsday/build/win32/qmake_msvc.py
@@ -0,0 +1,111 @@
# Python script for generating a Microsoft Visual Studio solution from doomsday.pro

import os, sys, re

print "\nVISUAL STUDIO SOLUTION GENERATOR FOR DOOMSDAY\n"
print "Author: <jaakko.keranen@iki.fi>\n"

# Figure out the Doomsday root path.
rootPath = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..', '..'))
solPath = os.path.abspath(os.path.join(rootPath, '..', 'doomsday-msvc-build'))

print "Doomsday root path:", rootPath
print "Solution location: ", solPath

if not os.path.exists(solPath): os.mkdir(solPath)

# Run qmake to generate the solution and vcprojs.
os.chdir(solPath)
#os.system(os.path.join(rootPath, 'build', 'win32', 'qmake_tp_vc.bat'))

# Cleanup.
print "\nDeleting spurious PK3s..."
for name in ['doomsday', 'libdoom', 'libheretic', 'libhexen', 'libdoom64']:
fn = "..\%s.pk3" % name
if os.path.exists(fn):
os.remove(fn)

print "\nPatching..."

def fileRegex(fn, pattern, repl, count=0, startAtPos=0):
text = file(fn, 'r').read()
skipped = text[:startAtPos]
text = text[startAtPos:]
text = re.sub(pattern, repl, text, count)
file(fn, 'w').write(skipped + text)

def fileRegOff(fn, pattern, startAtPos=0):
text = file(fn, 'r').read()
text = text[startAtPos:]
found = re.search(pattern, text)
return found.start()


fileRegex('libdeng2\deng2.vcxproj',
r'=\\&quot;([A-Za-z0-9_\- ]+)\\&quot;',
r'=&quot;\1&quot;')

copyScript = 'python &quot;%s\\\\build\win32\copy_to_products.py' % rootPath + '&quot; &quot;' + solPath + '&quot;'
rcDirs = '&quot;' + rootPath + '\\\\api&quot;;&quot;' + rootPath + '\\\\libdeng1\include' + '&quot;'

def find_projs(path):
found = []
for name in os.listdir(path):
fn = os.path.join(path, name)
if os.path.isdir(fn) and '.' not in name:
found += find_projs(fn)
elif name[-8:] == '.vcxproj':
found.append(os.path.join(path, name))
return found

allProjs = find_projs(solPath)

print "Found %i projects." % len(allProjs)

for fn in allProjs:
pName = os.path.basename(fn)
pName = pName[:pName.index('.')]

# Fix target names.
fileRegex(fn, '[0-2]</PrimaryOutput>', '</PrimaryOutput>')
fileRegex(fn, '[0-2]</TargetName>', '</TargetName>')

# Add a post-build step for Debug config.
start = fileRegOff(fn, r'<ItemDefinitionGroup Condition.*Debug\|Win32')
fileRegex(fn,
r'</ResourceCompile>\n',
r"""</ResourceCompile>
<PostBuildEvent>
<Command>""" + copyScript + r""" Debug</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy """ + pName + r""" to products/bin</Message>
</PostBuildEvent>\n""", 1, start)

# Tell RC where to find headers.
fileRegex(fn,
r'</ResourceCompile>\n',
r""" <AdditionalIncludeDirectories>""" + rcDirs + """</AdditionalIncludeDirectories>\n </ResourceCompile>\n""",
1, start)

# Add a post-build step for Release config.
start = fileRegOff(fn, r'<ItemDefinitionGroup Condition.*Release\|Win32')

fileRegex(fn,
r'</ResourceCompile>\n',
r"""</ResourceCompile>
<PostBuildEvent>
<Command>""" + copyScript + r""" Release</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy """ + pName + r""" to products/bin</Message>
</PostBuildEvent>\n""", 1, start)

# Tell RC where to find headers.
fileRegex(fn,
r'</ResourceCompile>\n',
r""" <AdditionalIncludeDirectories>""" + rcDirs + """</AdditionalIncludeDirectories>\n </ResourceCompile>\n""",
1, start)

print "\nAll done!\n"
print 'Solution generated:', os.path.join(solPath, 'doomsday.sln')
8 changes: 8 additions & 0 deletions doomsday/build/win32/qmake_tp_vc.bat
@@ -0,0 +1,8 @@
@echo off
REM -- Generates a Visual Studio solution and vcprojs for the project.
REM -- Note: Expected to be called by qmake_msvc.py.

REM -- Set up the build environment.
call ..\doomsday\build\win32\envconfig.bat

qmake -tp vc -r ..\doomsday\doomsday.pro

0 comments on commit af74de2

Please sign in to comment.