Что до Scala - то она пока радует. Чему способствует хорошая книжка, а так же полезные ресурсы, например, вот.
И так-же хорошая интеграция в Idea при помощи plugin'ов, позволяя совершенно без проблем совмещать scala & lrgacy java код с первых минут использования.
Единственный `затык`, встреченный на данный момент, оказалась сборка из командной строки. Сама сборка была построена на Scons, в связи с большим объемом кода плюсового, и некоторой генерации. А Java код собирался вызываемым из Scons ant'ом, по сгенерированной идеей 'build.xml'.
Но для Scala, на данный момент, не генерируется необходимых целей сборки, в связи с чем пришлось искать обходные пути.
Ставились требования разработки в Idea и поддержания скрипта сборки в валидном состоянии простыми автоматическими действиями. Были попробованы SBT и Maven, но я не понял, как после генерации ими проектов по простому получить параллельно работающие ветви и в Ide и для command line (а SBT так просто повеселила своим названием, так как она для вхождения вовсе не simple - по прочтению ~ 8 страниц мануала у меня не было четкого понимания, как нужно описывать проекты, их структуру и т.д. .. да банально не мог сходу написать простой рабочий проект где не все по умолчанию).
В результате немного подсмотрев, как по простому собирать ant для сборки scala, был допилен модификатор Idea'вских ant'овых скриптов, собственно который и решил данную задачу (на данный момент).
Питоновский код (в виде Scons билдера) под 'катом' (python converter for idea ant build xml):
import xml.etree.ElementTree as ET
def setMainClass(jar, className):
# find manifest
manifest = jar.find('manifest')
if manifest is None :
# create if no
manifest = ET.SubElement(jar, 'manifest')
# find main class attribute
for attribute in manifest.findall('attribute'):
if attribute.attrib.get('name', '') == Main-Class:
return
# set, if no
ET.SubElement(manifest, 'attribute').attrib.update({
'name' : 'Main-Class',
'value' : className
})
def setMainClasses(root, jar2MainClass):
for jar in root.findall('.//jar'):
for jarName,className in jar2MainClass.items():
if jar.attrib.get('destfile', '').find(jarName) != -1:
setMainClass(jar, className)
break
def addScalac(root):
#
# find scala libs
#
scala_library = None
scala_compiler = None
for pathelem in root.findall('.//pathelement'):
location = pathelem.attrib.get('location', '')
if location.endswith('scala-library.jar'):
scala_library = location
elif location.endswith('scala-compiler.jar'):
scala_compiler = location
assert(scala_library and scala_compiler)
#
# insert scala init target
#
scala_init = ET.SubElement(root, 'target')
scala_init.attrib['name'] = 'init_scalac'
ET.SubElement(scala_init, 'property').attrib.update({
'name' : 'scala-library.jar',
'value' : scala_library
})
scala_task = ET.SubElement(scala_init, 'taskdef')
scala_task.attrib['resource']='scala/tools/ant/antlib.xml'
scapa_cp = ET.SubElement(scala_task, 'classpath')
ET.SubElement(scapa_cp, 'pathelement').attrib['location'] = scala_compiler
ET.SubElement(scapa_cp, 'pathelement').attrib['location'] = '${scala-library.jar}'
#
# insert scala bild targets
#
# Nodes with name='Singapore' that have a 'javac' child
for target in root.findall('.//target'):
javac = target.find('javac')
if javac is None:
continue
target.attrib['depends'] = 'init_scalac' if not target.attrib.has_key('depends') else target.attrib['depends'] + ',init_scalac'
scalac = ET.Element('scalac')
target.insert(list(target).index(javac), scalac)
scalac.insert(0, javac.find('classpath'))
ET.SubElement(scalac, 'include').attrib['name'] = '**/*.scala'
ET.SubElement(scalac, 'include').attrib['name'] = '**/*.java'
scalac.attrib.update({
'force' : 'changed',
'srcref' : javac.find('src').attrib['refid'],
'destdir': javac.attrib['destdir']
})
def ideaAntUpdater(target, source, env):
tree = ET.parse(str(source[0]))
root = tree.getroot()
if env.get('jar2MainClass', None):
setMainClasses(root, env['jar2MainClass'])
if env.get('scala', False):
addScalac(root)
tree.write(str(target[0]))
return 0
def ideaAntEmitter(target, source, env):
env.Depends(target, env.Value(env.get('jar2MainClass', None)))
env.Depends(target, env.Value(env.get('scala', False)))
env.Depends(target, env.Value('Version: 1.0.1'))
return (target, source)
class Builder(object):
def __init__(self):
pass
def configure(self, env):
env['BUILDERS']['IdeaAntUpdater'] = env.Builder(
action = ideaAntUpdater,
emitter = ideaAntEmitter
)
Комментариев нет:
Отправить комментарий