SBT

2015-04-11 20 views
9

'da modül bağımlılığı için özel sınıf bir yükleyici kullanıyorum, core ve third-party'dan oluşan çok modüllü bir SBT yapısı var. yapıdır kabaca bu:SBT

api 
|- core 
|- third-party 

third-party için kod api uygular ve başka bir yerden aynen kopyalanır, bu yüzden gerçekten dokunmak istemiyorum.

third-party yoldan uygulandığından (singletons'un yoğun kullanımı), core numaralı telefona third-party numaralı telefondan bağlanamıyorum. Özellikle, sadece api aracılığıyla kullanmam gerekiyor, ancak çalışma zamanında third-party'un birden çok kopyasını almam gerekiyor. (. Bu bana aynı anda birden "singletons" olmasını sağlar)

benim SBT yapı dışında koşuyorum, ben sadece bunu:

def createInstance(): foo.bar.API = { 
    val loader = new java.net.URLClassLoader("path/to/third-party.jar", parent) 
    loader.loadClass("foo.bar.Impl").asSubclass(classOf[foo.bar.API]).newInstance() 
} 

Ama sorun olduğunu ben don sbt core/run aracılığıyla çalıştırıyorsam ne zaman çalışma zamanında anlamaya karar verdim URLClassLoader için bir argüman olarak vermeliyim.

+1

1. Projeyi nasıl bir araya getirmeyi düşünüyorsunuz? sbt montaj? Yoksa üçüncü parti.jar harici olacak mı? 2. Üçüncü taraf singletonları nedir? nesne? Senden bahsettiğin için soruyorum çünkü .newInstance() –

+0

@DaleWijnand 1. Henüz karar vermedim, ama belki de 'api', 'çekirdek' ve Scala kütüphanesi ile üçüncü tarafın paketlenmesine izin vereceğim. .jar 'ayrı ayrı. – larsrh

+0

@DaleWijnand 2. Oldukça karmaşıktır. Temel olarak, üçüncü parti kütüphanesi bazı harici işlemleri yönetir. Bu işlemlerin çoğunu bir kerede halledebilir, ancak başlatılması gerekir. Başlatma üzerine, bir nesnenin içindeki bir haritayı (örneğin, bir literal Scala 'nesnesi'), örneğin; dış sürecin yolu. Kodumun bu harici işlemin birden çok yerini ele alabilmesi gerekiyor. – larsrh

cevap

4

Bu, çalışmanızla birlikte çalışmamasına rağmen çalışmalıdır.

Temel fikir, sınıf yolunu, çalışma zamanında kullanabileceğiniz bir dosyaya yazmasına izin vermektir. sbt-buildinfo zaten bunun için iyi bir temel sağlıyor, ben de burada kullanacağım, ama siz sadece ilgili kısımları çıkararak bu eklentiyi kullanamazsınız.

proje tanımına ekleyin: Çalışma zamanında

lazy val core = project enablePlugins BuildInfoPlugin settings (
    buildInfoKeys := Seq(BuildInfoKey.map(exportedProducts in (`third-party`, Runtime)) { 
    case (_, classFiles) ⇒ ("thirdParty", classFiles.map(_.data.toURI.toURL)) 
    }) 
    ... 

, bunu kullanın:

def createInstance(): foo.bar.API = { 
    val loader = new java.net.URLClassLoader(buildinfo.BuildInfo.thirdParty.toArray, parent) 
    loader.loadClass("foo.bar.Impl").asSubclass(classOf[foo.bar.API]).newInstance() 
} 

exportedProducts sadece proje (örn .../target/scala-2.10/classes/) için derlenmiş sınıfları içerir. Kurulumunuza bağlı olarak, fullClasspath yerine (bunun yanı sıra kütüphane Yetkilerini ve bağımlı projeleri de içerir) veya başka bir sınıf yolu ile ilgili anahtarı kullanmak isteyebilirsiniz.

+0

Kulağa harika geliyor, deneyeceğim. – larsrh

+0

Geç cevap için özür dilerim. Çözümünüz gerçekten işe yaradı, teşekkürler. – larsrh