Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic distcc and ccache support to haikuporter #185

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion HaikuPorter/BuildPlatform.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,15 @@ def resolveDependencies(self, dependencyInfoFiles, requiresTypes,
return
resolver = DependencyResolver(self, requiresTypes, repositories,
**kwargs)
return resolver.determineRequiredPackagesFor(dependencyInfoFiles)
resolver.determineRequiredPackagesFor(dependencyInfoFiles)
if Configuration.shallUseCcache():
resolver.injectDependency('Required by configuration', 'cmd:ccache')
if Configuration.shallUseDistcc():
# pump needs its own switch and is out of my scope.
# see https://preview.tinyurl.com/y32dmfrv -- possible breakage!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really can't guarantee that sources/headers don't change during the build like that apparently requires, as there are lots of packages which do that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. cmd:pump is the thing that really needs that to be true, so I didn't hook that up (and isn't functional without python3). There is still a chance that an overly-clever build script might try to invoke pump on its own volition, though, which is the scary part of that. I don't have an example of this happening, but compare to WebKit, which will detect and automatically use ld.gold if it is available (which would make linking fail on haikuwebkit, but doesn't exist right now so isn't specifically an issue)

resolver.injectDependency('Required by configuration', 'cmd:distcc')
# is it worth pulling in ssh for "secure pump"? Probably not.
return resolver.getResult()


# -- BuildPlatformHaiku class -------------------------------------------------
Expand Down
34 changes: 34 additions & 0 deletions HaikuPorter/Configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ def isExecutable(path):

# allowed types of the configuration file values
haikuportsAttributes = {
'USE_DISTCC': {
'type': YesNo,
'required': False,
'default': False,
'extendable': Extendable.NO,
'indexable': False,
'setAttribute': 'useDistcc',
},
'USE_CCACHE': {
'type': YesNo,
'required': False,
'default': False,
'extendable': Extendable.NO,
'indexable': False,
'setAttribute': 'useCcache',
},
'ALLOW_UNTESTED': {
'type': YesNo,
'required': False,
Expand Down Expand Up @@ -253,6 +269,8 @@ def __init__(self):
self.vendor = None
self.packagesPath = None
self.sourceforgeMirror = None
self.useCcache = False
self.useDistcc = False

self._readConfigurationFile()

Expand Down Expand Up @@ -374,6 +392,22 @@ def getSourceforgeMirror():
def getVendor():
return Configuration.configuration.vendor

@staticmethod
def shallUseCcache():
return Configuration.configuration.useCcache

@staticmethod
def shallUseDistcc():
return Configuration.configuration.useDistcc

@staticmethod
def setUseDistcc(yes=True):
Configuration.configuration.useDistcc = yes

@staticmethod
def setUseCcache(yes=True):
Configuration.configuration.useCcache = yes

def _readConfigurationFile(self):
# Find the configuration file. It may be
# * specified on the command line,
Expand Down
16 changes: 16 additions & 0 deletions HaikuPorter/DependencyResolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ def determineRequiredPackagesFor(self, dependencyInfoFiles):
self._satisfiedPackagesCache += result
return result

def injectDependency(self, reason, requirement):
self._addImmediate(reason, ResolvableExpression(requirement),
'build_prerequires', True)
self._buildDependencyGraph()
result = [
node.path for node in self._packageNodes
]
return result

def getResult(self):
result = [
node.path for node in self._packageNodes
]
return result


def _populateProvidesManager(self):
for repository in self._repositories:
for entry in os.listdir(repository):
Expand Down
10 changes: 10 additions & 0 deletions HaikuPorter/Main.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,10 @@ def _buildMainPort(self, port, testPort):
'resolving build dependencies failed: {}'.format(exception))
return
else:
if self.options.useCache:
Configuration.setUseCcache(True)
if self.options.useDistcc:
Configuration.setUseDistcc(True)
buildDependencies = port.resolveDependencies(
self.packageRepositories, testPort)

Expand Down Expand Up @@ -676,6 +680,12 @@ def _buildPort(self, port, parseRecipe, testPort):
if self.options.patch:
port.patchSource()

if self.options.useCcache:
Configuration.setUseCcache(True)

if self.options.useDistcc:
Configuration.setUseDistcc(True)

if self.options.build:
port.build(self.packagesPath, self.options.package, targetPath)

Expand Down
10 changes: 10 additions & 0 deletions HaikuPorter/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,16 @@ def parseOptions():
dest='activeVersionsOnly', default=False,
help='only check in active versions of ports instead of all ports')

parser.add_option('--use-ccache', action='store_true',
dest='useCcache', default=False,
help='Use ccache to accelerate building by caching artefacts '
+ '(Uses ccache from ~)')

parser.add_option('--use-distcc', action='store_true',
dest='useDistcc', default=False,
help='Use Distcc to offload compilation to other machinesi '
+ '(uses configuration from ~/config)')

global __Options__

(__Options__, args) = parser.parse_args()
Expand Down
13 changes: 13 additions & 0 deletions HaikuPorter/Port.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
getShellVariableSetters,
recipeActionScript,
setupChrootScript,
setupDistccScript,
setupCcacheScript,
)
from .Source import Source
from .Utils import (
Expand Down Expand Up @@ -77,6 +79,12 @@ def __enter__(self):
shellEnv.update(self.envVars)
check_output(['bash', '-c', setupChrootScript], env=shellEnv,
cwd=self.path)
if Configuration.shallUseCcache():
check_output(['bash', '-c', setupCcacheScript],
env=shellEnv, cwd=self.path)
if Configuration.shallUseDistcc():
check_output(['bash', '-c', setupDistccScript],
env=shellEnv, cwd=self.path)
return self

def __exit__(self, ignoredType, value, traceback):
Expand Down Expand Up @@ -1564,6 +1572,11 @@ def _openShell(self, params, targetDir, env):
# define a terminal
shellEnv['TERM'] = 'xterm'

if Configuration.shallUseDistcc():
shellEnv['HOME'] = '/boot/home'
if Configuration.shallUseCcache():
shellEnv['CCACHE_PREFIX'] = 'distcc'

# execute the requested action via a shell ...
args = ['bash']
args += params
Expand Down
89 changes: 89 additions & 0 deletions HaikuPorter/ShellScriptlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,95 @@ def getShellVariableSetters(shellVariables):
'''


# -----------------------------------------------------------------------------

# Shell scriptlet which sets up ccache in chroot
# MUST be called BEFORE distcc setup!
# we add distcc to the chain if req'd by passing an extra environment variable.
# Something like CCACHE_PREFIX=distcc and we let computer find it for us
# We don't remove this on success: cache might be reused after a patch
setupCcacheScript = r'''

if ! [ -e boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper ]; then

# this is the first thing in $PATH after . so we're jumping in front of gcc
mkdir -p boot/home/config/non-packaged/bin

# catch unprefixed invocations and redo them correctly
echo '#!/bin/bash
exec '$targetArchitecture'-unknown-haiku-g${0:$[-2]} "$@"' > \
boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper
chmod a+x boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper

# we add the prefix because otherwise both machines just use 'gcc'
# and i can't link linux objects to haiku objects so that fails
ln -s /bin/ccache boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-c++
ln -s /bin/ccache boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-g++
ln -s /bin/ccache boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-gcc
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/cc
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/gcc
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/g++
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/c++

# this stops the gxx from above from falling straight through to /bin/gxx
mkdir -p boot/home/config/bin
ln -s /bin/c++ boot/home/config/bin/$targetArchitecture-unknown-haiku-c++
ln -s /bin/g++ boot/home/config/bin/$targetArchitecture-unknown-haiku-g++
ln -s /bin/gcc boot/home/config/bin/$targetArchitecture-unknown-haiku-gcc
ln -s /bin/cc boot/home/config/bin/$targetArchitecture-unknown-haiku-cc
fi

# ?? We don't want to lose this but a soft link can't point to the real directory. it still helps...
if ! [ -e boot/home/.ccache.ccache.conf ]; then
mkdir -p boot/home/.ccache
cp /boot/home/.ccache/ccache.conf boot/home/.ccache
fi

'''


# -----------------------------------------------------------------------------

# Shell scriptlet which sets up distcc in chroot
setupDistccScript = r'''

if ! [ -e boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper ]; then

# this is the first thing in $PATH after . so we're jumping in front of gcc
mkdir -p boot/home/config/non-packaged/bin

# catch unprefixed invocations and redo them correctly
echo '#!/bin/bash
exec '$targetArchitecture'-unknown-haiku-g${0:$[-2]} "$@"' > \
boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper
chmod a+x boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper
ln -s /bin/distcc boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-c++
ln -s /bin/distcc boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-g++
ln -s /bin/distcc boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-gcc

# we add the prefix because otherwise both machines just use 'gcc'
# and i can't link linux objects to haiku objects so that fails
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/cc
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/gcc
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/g++
ln -s /boot/home/config/non-packaged/bin/$targetArchitecture-unknown-haiku-wrapper boot/home/config/non-packaged/bin/c++

# this stops the gxx from above from falling straight through to /bin/gxx
mkdir -p boot/home/config/bin
ln -s /bin/c++ boot/home/config/bin/$targetArchitecture-unknown-haiku-c++
ln -s /bin/g++ boot/home/config/bin/$targetArchitecture-unknown-haiku-g++
ln -s /bin/gcc boot/home/config/bin/$targetArchitecture-unknown-haiku-gcc
ln -s /bin/cc boot/home/config/bin/$targetArchitecture-unknown-haiku-cc
fi

if ! [ -e boot/home/.distcc ]; then
# copy user's distcc setup into chroot so we know our volunteers etc
cp -R /boot/home/.distcc boot/home
fi

'''


# -----------------------------------------------------------------------------

# Shell scriptlet that prepares a chroot environment for entering.
Expand Down