Skip to content

Commit f636c14

Browse files
committed
Fixed missing build.py
1 parent c3ef77e commit f636c14

File tree

2 files changed

+247
-1
lines changed

2 files changed

+247
-1
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
build
1+
/build
22
install
33
*.config
44
*.creator*

dependencies/build/build.py

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#! /usr/bin/env python
2+
3+
import argparse
4+
import glob
5+
import os
6+
import multiprocessing
7+
import re
8+
import subprocess
9+
import shutil
10+
import sys
11+
import tarfile
12+
import urllib
13+
import zipfile
14+
15+
def __projects() :
16+
17+
configFiles = glob.glob( "*/config.py" )
18+
return [ os.path.split( f )[0] for f in configFiles ]
19+
20+
def __decompress( archive ) :
21+
22+
if os.path.splitext( archive )[1] == ".zip" :
23+
with zipfile.ZipFile( archive ) as f :
24+
for info in f.infolist() :
25+
extracted = f.extract( info.filename )
26+
os.chmod( extracted, info.external_attr >> 16 )
27+
files = f.namelist()
28+
elif archive.endswith( ".tar.xz" ) :
29+
## \todo When we eventually move to Python 3, we can use
30+
# the `tarfile` module for this too.
31+
command = ""
32+
if sys.platform == "win32":
33+
command = "cmake -E tar xvf {archive}".format( archive=archive )
34+
else:
35+
command = "tar -xvf {archive}".format( archive=archive )
36+
sys.stderr.write( command + "\n" )
37+
files = subprocess.check_output( command, stderr=subprocess.STDOUT, shell = True )
38+
files = [ f for f in files.split( "\n" ) if f ]
39+
files = [ f[2:] if f.startswith( "x " ) else f for f in files ]
40+
else :
41+
with tarfile.open( archive, "r:*" ) as f :
42+
f.extractall()
43+
files = f.getnames()
44+
45+
dirs = { f.split( "/" )[0] for f in files if re.search( "warning:", f ) == None }
46+
if len( dirs ) == 1 :
47+
# Well behaved archive with single top-level
48+
# directory.
49+
return next( iter( dirs ) )
50+
else :
51+
# Badly behaved archive
52+
return "./"
53+
54+
def __loadConfig( project, buildDir, buildType, forceLibLinkType, forceCCompiler, forceCxxCompiler ) :
55+
56+
# Load file. Really we want to use JSON to
57+
# enforce a "pure data" methodology, but JSON
58+
# doesn't allow comments so we use Python
59+
# instead. Because we use `eval` and don't expose
60+
# any modules, there's not much beyond JSON
61+
# syntax that we can use in practice.
62+
63+
with open( project + "/config.py" ) as f :
64+
config =f.read()
65+
66+
config = eval( config )
67+
68+
# Apply platform-specific config overrides.
69+
70+
config["platform"] = "platform:{}".format({ "darwin": "osx", "linux":"linux", "win32": "windows"}.get( sys.platform, "linux" ))
71+
platformOverrides = config.pop( config["platform"], {} )
72+
73+
unused_keys = [key for key, value in config.items() if "platform:" in key]
74+
for key in unused_keys:
75+
config.pop( key, None )
76+
77+
for key, value in platformOverrides.items() :
78+
79+
if isinstance( value, dict ) and key in config :
80+
config[key].update( value )
81+
else :
82+
config[key] = value
83+
84+
# Apply variable substitutions.
85+
86+
variables = config.get( "variables", {} ).copy()
87+
libLinkType = ""
88+
libLinkTypes = config.get( "libLinkType", {} ).copy()
89+
if( libLinkTypes ) :
90+
if( forceLibLinkType == "shared" ) :
91+
libLinkType = libLinkTypes.get("shared", "")
92+
elif( forceLibLinkType == "static" ) :
93+
libLinkType = libLinkTypes.get("static", "")
94+
elif( forceLibLinkType == "default" ) :
95+
libLinkType = libLinkTypes.get("default", "")
96+
else :
97+
if( forceLibLinkType != "default" ) :
98+
print( "Warning --forceLibLinkType %s is set but there is no config for this" % forceLibLinkType )
99+
cmake_generator = "\"NMake Makefiles JOM\"" if config["platform"] == "platform:windows" else "\"Unix Makefiles\""
100+
boostBuildType = "release"
101+
cmakeBuildType = "Release"
102+
if buildType == "debug":
103+
cmakeBuildType = "Debug"
104+
boostBuildType = "debug"
105+
elif buildType == "relWithDebInfo":
106+
cmakeBuildType = "RelWithDebInfo"
107+
default_variables = {
108+
"buildDir" : buildDir,
109+
"buildDirFwd" : buildDir.replace("\\", "/"),
110+
"jobs" : multiprocessing.cpu_count(),
111+
"cmakeGenerator" : cmake_generator,
112+
"cmakeBuildType": buildType,
113+
"boostBuildType" : buildType,
114+
"libLinkType" : libLinkType,
115+
"cCompiler" : forceCCompiler,
116+
"cxxCompiler" : forceCxxCompiler,
117+
}
118+
missing_variables = { k:v for (k, v) in default_variables.items() if k not in variables }
119+
variables.update( missing_variables )
120+
121+
if config["platform"] == "platform:windows":
122+
# make sure JOM is in the path
123+
path_variable = ""
124+
if "environment" in config:
125+
path_variable = os.path.expandvars(config["environment"].get("PATH", "%PATH%"))
126+
config["environment"].update( { "PATH": path_variable + ";%ROOT_DIR%\\winbuild\\jom" } )
127+
else:
128+
config["environment"] = { "PATH": "%PATH%;%ROOT_DIR%\\winbuild\\jom" }
129+
130+
def __substitute( o ) :
131+
132+
if isinstance( o, dict ) :
133+
return { k : __substitute( v ) for k, v in o.items() }
134+
elif isinstance( o, list ) :
135+
return [ __substitute( x ) for x in o ]
136+
elif isinstance( o, tuple ) :
137+
return tuple( __substitute( x ) for x in o )
138+
elif isinstance( o, str ) :
139+
while True :
140+
s = o.format( **variables )
141+
if s == o :
142+
return s
143+
else :
144+
o = s
145+
146+
return __substitute( config )
147+
148+
def __buildProject( project, buildDir, buildType, forceLibLinkType, forceCCompiler, forceCxxCompiler ) :
149+
150+
config = __loadConfig( project, buildDir, buildType, forceLibLinkType, forceCCompiler, forceCxxCompiler )
151+
152+
archiveDir = project + "/archives"
153+
if not os.path.exists( archiveDir ) :
154+
os.makedirs( archiveDir )
155+
156+
archives = []
157+
for download in config["downloads"] :
158+
159+
archivePath = os.path.join( archiveDir, os.path.basename( download ) )
160+
archives.append( archivePath )
161+
162+
if os.path.exists( archivePath ) :
163+
continue
164+
165+
sys.stderr.write( "Downloading {}".format( download ) + "\n" )
166+
urllib.urlretrieve( download, archivePath )
167+
168+
workingDir = project + "/working"
169+
if os.path.exists( workingDir ) :
170+
shutil.rmtree( workingDir )
171+
os.makedirs( workingDir )
172+
os.chdir( workingDir )
173+
174+
decompressedArchives = [ __decompress( "../../" + a ) for a in archives ]
175+
os.chdir( config.get( "workingDir", decompressedArchives[0] ) )
176+
177+
if config.get("license") is not None :
178+
licenseDir = os.path.join( buildDir, "doc/licenses" )
179+
if not os.path.exists( licenseDir ) :
180+
os.makedirs( licenseDir )
181+
shutil.copy( config["license"], os.path.join( licenseDir, project ) )
182+
183+
patch_command = "%ROOT_DIR%\\winbuild\\patch\\bin\\patch" if config["platform"] == "platform:windows" else "patch"
184+
for patch in glob.glob( "../../patches/*.patch" ) :
185+
subprocess.check_call( "{patch_command} -p1 < {patch}".format( patch = patch, patch_command = patch_command ), shell = True )
186+
for patch in glob.glob( "../../patches/{}/*.patch".format( config["platform"].lstrip( "platform:" ) ) ) :
187+
subprocess.check_call( "{patch_command} -p1 < {patch}".format( patch = patch, patch_command = patch_command ), shell = True )
188+
189+
if config["platform"] == "platform:windows" and "LD_LIBRARY_PATH" in config.get( "environment", {} ) :
190+
config["environment"]["PATH"] = "{0};{1}".format( config["environment"]["LD_LIBRARY_PATH"], config["environment"].get( "PATH", "%PATH%" ) )
191+
192+
environment = os.environ.copy()
193+
for k, v in config.get( "environment", {} ).items() :
194+
environment[k] = os.path.expandvars( v )
195+
196+
for command in config["commands"] :
197+
sys.stderr.write( command + "\n" )
198+
subprocess.check_call( command, shell = True, env = environment )
199+
200+
for link in config.get( "symbolicLinks", [] ) :
201+
if os.path.exists( link[0] ) :
202+
os.remove( link[0] )
203+
os.symlink( link[1], link[0] )
204+
205+
parser = argparse.ArgumentParser()
206+
207+
parser.add_argument(
208+
"--project",
209+
choices = __projects(),
210+
help = "The project to build."
211+
)
212+
213+
parser.add_argument(
214+
"--buildDir",
215+
required = True,
216+
help = "The directory to put the builds in."
217+
)
218+
219+
parser.add_argument(
220+
"--buildType",
221+
choices = ["release", "debug", "relWithDebInfo"],
222+
default = "release",
223+
help = "The build type eg. release, debug, relWithDebInfo (relWithDebInfo is CMake only, reverts to release on other build systems). Default is release."
224+
)
225+
226+
parser.add_argument(
227+
"--forceLibLinkType",
228+
choices = ["default", "shared", "static"],
229+
default = "default",
230+
help = "The library type for linking eg. default, shared, static (default will use the recommended linking)."
231+
)
232+
233+
parser.add_argument(
234+
"--forceCCompiler",
235+
default = "gcc",
236+
help = "Force a particular C compiler."
237+
)
238+
239+
parser.add_argument(
240+
"--forceCxxCompiler",
241+
default = "g++",
242+
help = "Force a particular C++ compiler."
243+
)
244+
245+
args = parser.parse_args()
246+
__buildProject( args.project, args.buildDir, args.buildType, args.forceLibLinkType, args.forceCCompiler, args.forceCxxCompiler )

0 commit comments

Comments
 (0)