def __init__(self): self.licenses = {} for i in filelist(AIRSTRIP_LICENSES).get(): d = fs.readfile(i).split('\n\n') licenseurl = d.pop(0) licensecontent = '\n\n'.join(d) name = fs.basename(i).split('.').pop(0).upper() self.licenses[name] = {"name": name, "url": licenseurl, "content": licensecontent}
def docommand(args = "", preexec= "", insrc = False): # XXX somewhat condemned to work in the source tree itself... # If no prefix is provided, it is assumed (LEGACY) we are in the src dir, otherwise, we are in the pwd, and any command gets prefixed with the passed p p = fs.join(environ.src, technicolor.local) if not insrc else environ.pwd # This is XXX HACKISH if insrc: args = "%s/%s" % (fs.join(environ.src, technicolor.local), args) return shell.execute(environ.flush(), args, p, preexec)
def remove(self, name): if not name or not name.upper() in self.licenses: raise error.License(error.MISSING, "Trying to remove non existent license %s" % name) name = name.upper() del self.licenses[name] p = fs.join(AIRSTRIP_LICENSES, name) fs.remove(p)
def __wrap__(self, path, command): if fs.realpath('.') == fs.realpath(path): raise error.License(error.TERRIBLE, "Trying to manipulate current path .git (%s)!" % path) std = Std() sh('cd "%s";' % path, std = std) # XXX dead broken right now # if std.err: # raise error.License(error.TERRIBLE, "Can't change pwd! (%s)!" % path) sh('cd "%s"; git %s' % (path, command), std = std)
def edit(self, name): if not name: raise error.License(error.WRONG_ARGUMENT, "You need to pass a non-empty license name to the edit method") name = name.upper() path = fs.join(AIRSTRIP_LICENSES, name) if not name in self.licenses: self.licenses[name] = EMPTY_LICENSE.replace('{name}', name) fs.writefile(path, self.licenses[name]) sh('open "%s"' % path, output = False)
def __init__(self): if not fs.exists(AIRSTRIP_RC_PATH): fs.writefile(AIRSTRIP_RC_PATH, json.dumps(EMPTY_RC, indent = 2)) try: self.rc = json.loads(fs.readfile(AIRSTRIP_RC_PATH)) except: raise error.AirRC(error.BROKEN, "Your airstrip rc file (%s) is horked! Please rm or fix it" % AIRSTRIP_RC_PATH) if not self.rc['version'] == API: self.__ask__()
def configure(args = "", preexec= "", debug='disable', shared='shared', deptrack = '', hosttarget = 'both'): if not shared: shared = '' else: shared = '--disable-shared --enable-static' if environ.static else '--enable-shared --disable-static' if not debug: debug = '' else: debug = '--enable-debug' if environ.debug else '--disable-debug' if deptrack == 'disable': deptrack = '--disable-dependency-tracking' else: deptrack = '' # XXXXXXXXXXXS STOOOPID # x86_64-apple-darwin11.2.0 host = '' if hosttarget == 'both': build = sh('echo `uname -m`-apple-darwin`uname -r`', output = False) if environ.get('MONADE_HOST') != build.strip(): host = '--host=%s --build=%s' % (environ.get('MONADE_HOST'), build.strip()) act = fs.join(environ.src, technicolor.local, 'configure') command = '%s %s --with-pic --prefix="%s" %s %s %s %s' % (act, deptrack, environ.prefix, shared, debug, host, args) shell.execute(environ.flush(), command, environ.pwd, preexec)
def bootstrap(args = "", preexec= ""): if fs.exists(fs.join(environ.src, technicolor.local, 'bootstrap')): command = fs.join(environ.src, technicolor.local, 'bootstrap') elif fs.exists(fs.join(environ.src, technicolor.local, 'bootstrap.sh')): command = fs.join(environ.src, technicolor.local, 'bootstrap.sh') elif fs.exists(fs.join(environ.src, technicolor.local, '..', 'bootstrap')): command = fs.join(environ.src, technicolor.local, '..', 'bootstrap') else: console.fail('Calling bootstrap but there is nothing like that around!') command = '%s --prefix="%s" --with-toolset=$MY_BOOST_TOOLSET %s' % (command, environ.prefix, args) # --libdir="%s/lib" environ.prefix, shell.execute(environ.flush(), command, environ.pwd, preexec)
def uninstall(deploy, target, build, name, toolchain = False): globals()['technicolor'] = yawn.get(name) if not technicolor.production: console.error('*NOT* going to remove everything!') return # Start with clean envs env.set(target, build) # Setup the prefixes env.native.prefix = fs.join(deploy, 'Toolchain', target) env.current.prefix = fs.join(deploy, target) # And tmp dirs # env.native.tmp = fs.join(roottmp, 'Toolchain') # env.current.tmp = fs.join(roottmp, target) path = __find(technicolor.production, env.native if toolchain else env.current, ignoresystem = True) if path: console.info("Found tracks of it. Removing production. %s" % path) fs.remove(path) else: console.error("The requested monade is NOT installed. Doing nothing.")
def b2(args = "", preexec= ""):#, local = False): # act = fs.join(environ.src, technicolor.local, 'b2') # if local: # command = '%s/b2 --debug-configuration --debug-building $MAKEFLAGS toolset=$MY_BOOST_TOOLSET $MY_BOOST_TARGET architecture=$MY_BOOST_ARCH address-model=$MY_BOOST_ADDR $MY_B2 --prefix=%s variant=release \ # --build-dir="%s" cxxflags="$CXXFLAGS" cflags="$CFLAGS" linkflags="$LDFLAGS" %s' % (local, environ.prefix, fs.join(environ.tmp, technicolor.local), args) # else: # # --debug-building command = 'b2 -q -a --debug-configuration $MAKEFLAGS toolset=$MY_BOOST_TOOLSET $MY_BOOST_TARGET architecture=$MY_BOOST_ARCH address-model=$MY_BOOST_ADDR $MY_B2 --prefix=%s \ --build-dir="%s" variant=%s link=%s %s' % (environ.prefix, fs.join(environ.tmp, technicolor.local), 'debug' if environ.debug else 'release', 'static' if environ.static else 'shared', args) # cxxflags="$CXXFLAGS" cflags="$CFLAGS" linkflags="$LDFLAGS" # --user-config=user-config.jam # using gcc : x86_64 : x86_64-pc-linux-g++ ; shell.execute(environ.flush(), command, environ.pwd, preexec)
def __init__(self, remote, path): # Require git on the system to have it sys.check_package('git') clean = re.sub('[.]git$', '', remote.split('/').pop()) self.local = fs.join(path, clean) self.remote = remote self.debug = False base = fs.dirname(self.local) if not fs.exists(base): fs.makedir(base) if not fs.exists(self.local): self.__clone__() else: self.__clean__() self.__rebase__()
def __clone__(self): self.__wrap__(fs.dirname(self.local), 'clone %s' % self.remote)
def flush(self): # Copy it so we keep a clean original object for later reuse save = copy.deepcopy(self.__data) # OSX stuff is specific if self.target == System.MACOS: sdk = self.get('MONADE_SDK') arch = self.get('MONADE_ARCH') if arch: # -arch is OSX specific, -march is generic but can't produce fat binaries, -m32, -m64 is the new syntax self.cflags('-arch %s' % arch) self.cxxflags('-arch %s' % arch) self.cppflags('-arch %s' % arch) self.objcflags('-arch %s' % arch) self.ldflags('-arch %s' % arch) if sdk: self.cflags('-isysroot %s' % sdk) self.cxxflags('-isysroot %s' % sdk) self.cppflags('-isysroot %s' % sdk) self.objcflags('-isysroot %s' % sdk) self.ldflags('-isysroot %s' % sdk) macomin = self.get('MONADE_MACO_MIN') if macomin: self.cflags('-mmacosx-version-min=%s' % macomin) self.cxxflags('-mmacosx-version-min=%s' % macomin) self.cppflags('-mmacosx-version-min=%s' % macomin) self.objcflags('-mmacosx-version-min=%s' % macomin) self.ldflags('-mmacosx-version-min=%s' % macomin) # If we have a prefix if self.prefix: # Includes inc = '-I%s' % FileSystem.join(self.prefix, 'include') self.cflags(inc) self.cxxflags(inc) self.cppflags(inc) self.objcflags(inc) self.ldflags('-L%s' % FileSystem.join(self.prefix, 'lib')) if native.prefix: # Add the bin path to the toolchain dir as well - careful! self.path(FileSystem.join(native.prefix, 'bin')) # This is tricky, each toolchain need to point this to the pc-path used to compile pkgconfig self.set('PKG_CONFIG_PATH', FileSystem.join(native.prefix, 'lib', 'pkgconfig')) # Should be added to support additional QT linking # pkgadd = self.get('PKGADD') # if pkgadd: # self.set('PKG_CONFIG_PATH', '%s:%s' % (FileSystem.join(self.prefix, 'lib', 'pkgconfig'), '/Volumes/dandinette/roxeebackup-20130521/bin32/qt/5.0.2-ming/5.0.2/mingw47_32/lib/pkgconfig')) # CMAKE stuff self.set('CMAKE_PREFIX_PATH', self.prefix) self.set('CMAKE_INSTALL_PREFIX', self.prefix) # self.set('CMAKE_CXX_FLAGS', self.get('CFLAGS')) # self.set('CMAKE_LD_FLAGS', self.get('LDFLAGS')) self.set('CMAKE_INCLUDE_PATH', FileSystem.join(self.prefix, 'include')) self.set('CMAKE_LIBRARY_PATH', FileSystem.join(self.prefix, 'lib')) # Add all the env, except the MONADE_ starting stuff send = [] for i in self.__data: if not i.startswith('MONADE_'): send.append('export %s="%s"' % (i, self.get(i))) # Guess the number of cores we could use, if not explicitely set to one # if !self.get('MAKEFLAGS'): # set('MAKEFLAGS', ) # `sysctl -n machdep.cpu.core_count` # Restore self.__data = save return send
def inreplace(filepath, find, replace): p = fs.join(environ.pwd, filepath) pun = fs.readfile(p) pun = pun.replace(find, replace) fs.writefile(p, pun)
def exists(name): p = fs.join(AIRSTRIP_LICENSES, name) if fs.exists(p) and fs.isfile(p, True): return p return False
def cmake(args = "", preexec= ""): command = 'cmake %s %s' % (fs.join(environ.src, technicolor.local), args) return shell.execute(environ.flush(), command, environ.pwd, preexec)
# -*- coding: utf8 -*- from puke import FileSystem as fs, FileList as filelist, sh as sh import os import error AIRSTRIP_ROOT = os.path.dirname(os.path.realpath(__file__)) # System-wide yawns path AIRSTRIP_LICENSES = fs.join(AIRSTRIP_ROOT, 'licenses') # XXX kind of dirty hack to have it in the git local repo instead of system-wide if fs.exists('airstrip/licenses'): AIRSTRIP_LICENSES = 'airstrip/licenses' # Template for empty RC EMPTY_LICENSE = """http://licenseurl Licensed under the {name} license. License text, bla.""" class Licenses(): def __init__(self): self.licenses = {} for i in filelist(AIRSTRIP_LICENSES).get(): d = fs.readfile(i).split('\n\n') licenseurl = d.pop(0) licensecontent = '\n\n'.join(d) name = fs.basename(i).split('.').pop(0).upper() self.licenses[name] = {"name": name, "url": licenseurl, "content": licensecontent}
def install(rootsrc, roottmp, deploy, target, build, name, toolchain = False, clean = False, cleanarchive = False, debug = False, static = False): globals()['technicolor'] = yawn.get(name) # If already done, for this target, during *this* session, silently pass - avoid verbose dependency checking and recursive references # (yeah, I'm looking at you goddamn pkgconfig) if (not toolchain) and (target in technicolor.done): return console.header("Target: %s - Build: %s - Yawn: %s (version %s - license %s)" % (target, build, technicolor.name, technicolor.version, technicolor.license), 1) # Start with clean envs env.set(target, build) # Setup the prefixes # XXX this totally sucks ass. Toolchain of a package may in turn depend on a specific tool, which makes it compiled into the Toolchain/Darwin directory # anyway... debug = not (not debug or (debug == "false")) static = not (not static or (static == "false")) env.native.prefix = fs.join(deploy, 'Toolchain', toolchain if toolchain else target) env.current.prefix = fs.join(deploy, target, 'debug' if debug else 'release', 'static' if static else 'dynamic') # And tmp dirs env.native.tmp = fs.join(roottmp, 'Toolchain', toolchain if toolchain else target) env.current.tmp = fs.join(roottmp, target, 'debug' if debug else 'release', 'static' if static else 'dynamic') # And src dirs env.native.src = fs.join(rootsrc, 'Toolchain', toolchain if toolchain else target) env.current.src = fs.join(rootsrc, target) console.header('Searching for it') if technicolor.production and __find(technicolor.production, env.native if toolchain else env.current, target != build): console.info("The requested monade seems to be already compiled and installed. Will do nothing.") technicolor.done[target] = True return else: console.info("Will build") console.header("Building tools") # Walk tool dependencies first and build them if need be for depname in technicolor.toolchain: # If we already are compiling a tool, forward the original toolchain value. If not, that will be the target forwardtoolchaintarget = toolchain if toolchain else target install(rootsrc, roottmp, deploy, build, build, depname, forwardtoolchaintarget, clean, cleanarchive) console.info('Done with tools') console.header('Building dependencies') # Get back to the original yawn now - XXX EXTREMELY bad design globals()['technicolor'] = yawn.get(name) # Walk dependencies and build them if need be for depname in technicolor.depends: # If we already are compiling a tool, forward the original toolchain value. If not, that will be the target forwardtoolchaintarget = toolchain if toolchain else False install(rootsrc, roottmp, deploy, target, build, depname, forwardtoolchaintarget, clean, cleanarchive, debug, static) console.info('Done with dependencies') # Get back to the original yawn now - XXX EXTREMELY bad design globals()['technicolor'] = yawn.get(name) env.set(target, build) env.current.debug = True if debug else False env.current.static = True if static else False env.native.prefix = fs.join(deploy, 'Toolchain', toolchain if toolchain else target) env.current.prefix = fs.join(deploy, target, 'debug' if debug else 'release', 'static' if static else 'dynamic') env.native.tmp = fs.join(roottmp, 'Toolchain', toolchain if toolchain else target) env.current.tmp = fs.join(roottmp, target, 'debug' if debug else 'release', 'static' if static else 'dynamic') env.native.src = fs.join(rootsrc, 'Toolchain', toolchain if toolchain else target) env.current.src = fs.join(rootsrc, target) console.header("Back onto Target: %s - Build: %s - Yawn: %s (version %s - license %s)" % (target, build, technicolor.name, technicolor.version, technicolor.license), 1) if not technicolor.url: console.warn('This is a dummy package with no url. Just passing by.') return # Load the python script file # sys.path.insert(0, 'monades') # currentjob = __import__('%s' % name) exec('from technicolor import %s as currentjob' % technicolor.name) # Ensure the package is here console.header('Getting remote stuff here') globals()['environ'] = env.native if toolchain else env.current # Set current directory now to source directory environ.pwd = fs.join(environ.src, technicolor.local) if technicolor.fetch(environ.src, cleanarchive): console.header("Got remote package, applying patches now.") technicolor.patch(environ.pwd, target) technicolor.copy(environ.pwd) if 'preprocess' in dir(currentjob): console.header('Preprocessing') currentjob.preprocess() else: console.warn('NO preprocessing specified for this monade. Going on.') else: console.warn("Output directory already exist. NOT getting package again and NOT running pre hook. If this is not acceptable, rm %s" % environ.pwd) # Ensure target dir are there to avoid complaints fs.makedir(fs.join(environ.prefix, 'lib')) fs.makedir(fs.join(environ.prefix, 'bin')) fs.makedir(fs.join(environ.prefix, 'include')) # Switch current directory now to temp directory environ.pwd = fs.join(environ.tmp, technicolor.local) if not fs.exists(environ.pwd): fs.makedir(environ.pwd) if 'configure' in dir(currentjob): # Exec console.header('Configure') currentjob.configure() else: console.warn('NO configure instructions specified for this monade! Going on.') if clean: if 'clean' in dir(currentjob): # Exec console.header('Clean') currentjob.clean() else: console.warn('NO clean instructions specified for this monade! Going on.') if 'make' in dir(currentjob): # Exec console.header('Make') currentjob.make() else: console.warn('NO make instructions specified for this monade! Going on.') # XXX switch this to deploy directory? console.header('Post-processing!', 1) if 'postprocess' in dir(currentjob): currentjob.postprocess() else: console.warn('NO post-process instructions specified for this monade! Going on.') technicolor.done[target] = True
def set(self, key, value): if key: self.rc[key] = value fs.writefile(AIRSTRIP_RC_PATH, json.dumps(self.rc, indent = 2))
def __find(production, envir, ignoresystem = False): # Initialize the environment for the given target # env.sethost(puke.Yak.XCC) # # Specify our deploy path # Currently, packages that are both compiled in a toolchain AND as native dependency override each other when it comes to pc files. # The only solution would be to maintain two different PKG_CONFIG... # Try pkg-config first # XXX This is massively broken when cross-compiling # if fs.exists(fs.join(env.native.prefix, 'bin', 'pkg-config')) and production != 'pkg-config': # command = 'pkg-config --modversion %s' % production # try: # console.info(' * Trying to find through pkg-config') # # First try our pkg-config # ret = shell.execute(envir.flush(), command, silent = True) # ret = shell.execute(envir.flush(), 'echo $PKG_CONFIG_PATH/%s.pc' % production) # console.info(' + Found package at %s' % ret.out.strip()) # return ret.out.strip() # except Exception as e: # console.info(' - Failed!') # else: # console.info(' * You don\'t have pkg-config (yet?)!') # Otherwise, try the production name, litterally verif = fs.join(envir.prefix, production) console.info(' * Trying to find the given filename %s' % verif) if fs.exists(verif): if verif == production: # Should NEVER happen - this is bad every inch console.warn(' + Found but... BEWARE! This is a system path and might not be portable (that being said, *you* specified it!): %s' % verif) else: console.info(' + Found package in: %s' % verif) return verif else: console.info(' - Failed!') console.info(' * Trying to find the package as a binary somewhere') # Finally, that may be a binary # XXX this first because on cross compiling, the path is not set to the local bin test = fs.join(envir.prefix, 'bin', production) if fs.exists(test): console.info(' + Found a binary here: %s' % test) return test # Dirty windows trick test = fs.join(envir.prefix, 'bin', '%s.exe' % production) if fs.exists(test): console.info(' + Found a binary here: %s' % test) return test command = 'which %s' % production try: ret = shell.execute(envir.flush(), command, silent = True) if ret.out.startswith(envir.prefix): console.info(' + Found a binary here: %s' % ret.out) else: if ignoresystem: return False console.error(' + Found a binary on the system (might cause compatibility problems!): %s' % ret.out) q = prompt('Do you want to build your own, or use the system package (type "system")?') if q != 'system': return False return ret.out.strip() except: pass console.info(' - Failed!') console.warn('Package production not found') return False