Это просто быстрое воспоминание о шагах, которые я предпринял, чтобы запустить свой собственный helloworld, используя scala-native. На самом деле я еще не начал подробно рассматривать родной язык scala, но идея, стоящая за ним, действительно хороша. Некоторые общие сведения о scala-native можно найти здесь:
- Репозиторий Github: https://github.com/scala-native/scala-native
- Презентация из Scaladays NY: https://github.com/densh/talks/blob/517b20c30dd4aaf390785039cdd002f623ea…
- Twitter, чтобы следовать: @scala_native
Поскольку scala-native зависит от доступности LLVM и Clang ++, эта настройка может отличаться в вашей среде, чем в моей. Я все еще на OS-X Yosemite:
1
2
3
4
|
$ sw_vers ProductName: Mac OS X ProductVersion: 10.10 . 3 BuildVersion: 14D136 |
Но для пользователей Mac шаги будут примерно такими же. Теперь давайте приступим к настройке среды, чтобы вы могли запустить пример проекта, предоставляемого scala-native, и мы также создадим базовый проект helloworld. Еще раз, эти шаги работали в моей среде, и ваши могут отличаться. Есть несколько проблем с github, за которыми вы можете следить или узнать больше о том, как настроить вашу среду.
Шаги, которые работали для меня, были следующие:
Проверка кода
Нам, конечно, сначала нужно получить код, из командной строки сделаем следующее:
1
2
3
4
5
6
7
|
$ git clone --recursive https: //github.com/scala-native/scala-native Cloning into 'scala-native' ... remote: Counting objects: 8295 , done. remote: Compressing objects: 100 % ( 14 / 14 ), done. remote: Total 8295 (delta 3 ), reused 0 (delta 0 ), pack-reused 8278 Receiving objects: 100 % ( 8295 / 8295 ), 1.31 MiB | 94.00 KiB/s, done. Resolving deltas: 100 % ( 2955 / 2955 ), done. |
Это должно, теоретически, получить вам все необходимые источники. Я, однако, столкнулся с первой проблемой, что субмодельная скала не вытащила правильно. Каким-то образом git хочет использовать аутентификацию с открытым ключом вместо https. Самый простой способ быстро решить эту проблему, просто сделать это:
01
02
03
04
05
06
07
08
09
10
11
12
|
$ cd scala- native /submodules $ git clone https: //github.com/scala/scala Cloning into 'scala' ... remote: Counting objects: 333614 , done. remote: Total 333614 (delta 0 ), reused 0 (delta 0 ), pack-reused 333613 Receiving objects: 100 % ( 333614 / 333614 ), 83.31 MiB | 5.63 MiB/s, done. Resolving deltas: 100 % ( 226320 / 226320 ), done. Checking connectivity... done. Checking out files: 100 % ( 10492 / 10492 ), done. $ cd scala $ git checkout 2.11 .x |
Публикуйте библиотеки локально
На данный момент у вас есть все необходимые источники, но при попытке его создать вы можете столкнуться со следующими проблемами:
1
2
3
4
5
6
7
8
|
# from the scala- native directory $ sbt > publish-local ... lots of output [trace] Stack trace suppressed: run last scalalib/compile:compileIncremental for the full output. [trace] Stack trace suppressed: run last javalib/compile:doc for the full output. [error] (scalalib/compile:compileIncremental) java.lang.NoClassDefFoundError: scala/scalanative/nscplugin/NirGlobalAddons$nirPrimitives$ [error] (javalib/compile:doc) java.nio.charset.MalformedInputException: Input length = 1 |
Почему-то, кажется, что-то не так с некоторыми скалярными вещами, что приводит к провалу нашего проекта. Откройте файл build.sbt и измените проект javalib . Чтобы решить эту проблему, мы можем просто отключить скалярные вещи, например, добавив следующие две строки:
1
2
|
sources in (Compile,doc) := Seq.empty, publishArtifact in packageDoc := false |
Сюда:
1
2
3
4
5
6
7
|
83 lazy val javalib = 84 project.in(file( "javalib" )). 85 settings(libSettings, 86 sources in (Compile,doc) := Seq.empty, 87 publishArtifact in packageDoc := false 88 ). 89 dependsOn(nativelib) |
Теперь снова выполните локальную публикацию, и это должно как минимум успешно завершиться:
1
2
3
4
5
|
> reload > publish-local ... again, lots of output [info] published ivy to /Users/jos/.ivy2/local/org.scala- native /scalalib_2. 11 / 0.1 -SNAPSHOT/ivys/ivy.xml [success] Total time: 17 s, completed May 14 , 2016 4 : 06 : 31 PM |
На данный момент мы можем попытаться запустить демонстрационное приложение, но вы, вероятно, столкнетесь со следующими двумя ошибками: (по крайней мере, я сделал)
1
2
3
4
5
6
7
8
|
# This one: /Users/jos/dev/git/scala- native -clean/scala- native /demo- native /target/scala- 2.11 /demonative-out.ll: 152 : 40 : error: expected '{' in function body declare double @ "llvm.sqrt.f64" ( double ) ^ # And this one rt.cpp: 3 : 10 : fatal error: 'gc.h' file not found #include <gc.h> |
Ах … плохо. Что-то еще пошло не так. Первая ошибка вызвана неправильной версией LLVM (требуется 3.7, у меня версия 3.6), а вторая — тем, что библиотеки Boehm GC недоступны.
Настройте LLVM и Clang ++ правильно
Я не знаю, какая версия на более новых версиях OS-X, но у меня все еще было 3.6:
1
2
3
4
|
$ clang++ -v Apple LLVM version 6.1 . 0 (clang- 602.0 . 49 ) (based on LLVM 3.6 .0svn) Target: x86_64-apple-darwin14. 3.0 Thread model: posix |
Чтобы это исправить, не вмешиваясь, возможно, в другие инструменты, в зависимости от 3.6, я использовал brew для установки 3.7 версии LLVM и Clang ++. Возможно, вам придется сначала сделать ** brew tap homebrew / version **, если вы не можете найти llvm37
01
02
03
04
05
06
07
08
09
10
11
12
|
$ brew install llvm37 --with-clang ==> Installing llvm37 from homebrew/versions ==> Downloading https: //homebrew.bintray.com/bottles-versions/llvm37-3.7.1.yosemite.bottle.1.tar.gz Already downloaded: /Library/Caches/Homebrew/llvm37- 3.7 . 1 .yosemite.bottle. 1 .tar.gz ==> Pouring llvm37- 3.7 . 1 .yosemite.bottle. 1 .tar.gz ==> Caveats Extra tools are installed in /usr/local/opt/llvm37/share/clang- 3.7 To link to libc++, something like the following is required: CXX= "clang++-3.7 -stdlib=libc++" CXXFLAGS= "$CXXFLAGS -nostdinc++ -I/usr/local/opt/llvm37/lib/llvm-3.7/include/c++/v1" LDFLAGS= "$LDFLAGS -L/usr/local/opt/llvm37/lib/llvm-3.7/lib" |
Вы можете увидеть каталог, в котором установлены Clang и LLVM. Прежде чем мы снова запустим SBT, нам нужно создать символическую ссылку, чтобы плагин мог найти правильный исполняемый файл clang .
1
2
|
$ cd /usr/local/opt/llvm37/bin $ ln -s clang++- 3.7 clang++ |
И, наконец, нам просто нужно обновить переменную PATH, чтобы она указала на каталог установки перед запуском SBT :
1
2
3
4
5
|
$ export PATH=/usr/local/opt/llvm37/bin:$PATH $ clang++ -v clang version 3.7 . 1 (tags/RELEASE_371/ final ) Target: x86_64-apple-darwin14. 3.0 Thread model: posix |
На данный момент у нас должна быть одна из наших проблем, поэтому давайте просто проверим, что произойдет, если мы попробуем запустить демо:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<br/> # go back to the directory where you cloned scala- native $ cd ~/dev/git/scala- native -clean/scala- native $ sbt > demoNative/run [info] Updating {file:/Users/jos/dev/git/scala- native -clean/scala- native /}demoNative... [info] Resolving org.scala-lang#scalap; 2.11 . 8 ... [info] Done updating. [info] Compiling 1 Scala source to /Users/jos/dev/git/scala- native -clean/scala- native /demo- native /target/scala- 2.11 /classes... warning: overriding the module target triple with x86_64-apple-macosx10. 10.0 [-Woverride-module] 1 warning generated. /Users/jos/.scalanative/rtlib- 0.1 -SNAPSHOT/rt.cpp: 3 : 10 : fatal error: 'gc.h' file not found #include <gc.h> ^ 1 error generated. |
Как видите, у нас на одну ошибку меньше, но все равно что-то не так
Установить библиотеку Boehm GC
Чего не хватает и на что указывает ошибка, так это библиотеки Boehm GC. Есть несколько способов установить это. Мы можем использовать предварительно упакованный экземпляр brew или просто загрузить исходные тексты напрямую и установить Boehm таким образом. В этом примере мы сделаем последнее. Это означает, что следуйте инструкциям здесь: http://hboehm.info/gc/
01
02
03
04
05
06
07
08
09
10
11
|
$ mkdir boehm $ cd boehm $ git clone https: //github.com/ivmai/libatomic_ops.git $ git clone https: //github.com/ivmai/bdwgc.git $ cd bdgwc $ ln -s ../libatomic_ops $ autoreconf -vif $ automake --add-missing $ ./configure $ make $ sudo make install |
Кроме того, вы также можете установить пакет bdw-gc в brew.
1
|
$ brew install bdw-gc |
И после этого добавьте следующий build.sbt в демонстрационный проект с дополнительными настройками clang:
1
2
|
$ cat build.sbt nativeClangOptions := Seq( "-I/usr/local/Cellar/bdw-gc/7.4.2/include" , "-L/usr/local/Cellar/bdw-gc/7.4.2/lib" ) |
Однако я предпочитаю установку из источника *. На данный момент мы должны запустить демо.
1
2
3
4
|
> demoNative/run warning: overriding the module target triple with x86_64-apple-macosx10. 10.0 [-Woverride-module] 1 warning generated. Rendering ( 8 spp) 100.00 %[success] Total time: 13 s, completed May 14 , 2016 6 : 30 : 42 PM |
Woohoo … успех !!! Чтобы увидеть, что мы на самом деле выполняем код, сделаем небольшое изменение в источнике в каталоге demoNative. В файле smallpt.scala измените количество семплов на 8 следующим образом:
1
2
3
4
|
153 final val W = 800 154 final val H = 600 155 final val SAMPLES = 8 156 def main(args: Array[String]): Unit = { |
Теперь запустите программу снова (что должно занять намного больше времени):
1
2
3
4
5
|
> demoNative/run [info] Compiling 1 Scala source to /Users/jos/dev/git/scala- native -clean/scala- native /demo- native /target/scala- 2.11 /classes... warning: overriding the module target triple with x86_64-apple-macosx10. 10.0 [-Woverride-module] 1 warning generated. Rendering ( 32 spp) 100.00 %[success] Total time: 52 s, completed May 14 , 2016 6 : 34 : 11 PM |
Кажется, это работает. Кстати, результатом этой программы является трехмерная отрисованная сцена (пример программы — raytracer). Если вы установите большое количество сэмплов, вы получите довольно хороший рендер:
Мы также можем проверить, является ли вывод настоящей нативной программой:
1
2
3
4
5
|
otool -L demonative-out demonative-out: /usr/local/lib/libgc. 1 .dylib (compatibility version 2.0 . 0 , current version 2.3 . 0 ) /usr/lib/libc++. 1 .dylib (compatibility version 1.0 . 0 , current version 120.0 . 0 ) /usr/lib/libSystem.B.dylib (compatibility version 1.0 . 0 , current version 1213.0 . 0 ) |
Теперь давайте создадим пустой проект helloworld, где мы создадим собственную минимальную программу native-scala.
Helloworld scala-native
В проекте scala-native создайте новый каталог с именем helloworld-native. В этом каталоге создайте следующий файл (** helloworld.scala **):
01
02
03
04
05
06
07
08
09
10
|
package helloworld import scalanative. native ._, stdlib._ object Main { def main(args: Array[String]): Unit = { fprintf(__stdoutp, c "Hello World: Scala Native!!!" ) } } |
Прежде чем мы сможем запустить его, нам также необходимо обновить основной файл build.sbt и определить этот проект. Для этого добавьте следующее:
1
2
3
4
5
6
7
8
|
lazy val helloworldNative = project.in(file( "helloworld-native" )). settings(libSettings). settings( nativeVerbose := true , nativeClangOptions := Seq( "-O2" ) ). dependsOn(scalalib) |
Не забудьте использовать Seq («- I / usr / local / Cellar / bdw-gc / 7.4.2 / include», «-L / usr / local / Cellar / bdw-gc / 7.4.2 / lib») для Ваше определение сборки helloworld, если вы не устанавливаете Boehm GC с нуля.
Теперь перезагрузите sbt, и вы сможете запустить наше собственное scala-native приложение:
1
2
3
4
5
|
> helloworldNative/run [info] Compiling 1 Scala source to /Users/jos/dev/git/scala- native -clean/scala- native /helloworld- native /target/scala- 2.11 /classes... warning: overriding the module target triple with x86_64-apple-macosx10. 10.0 [-Woverride-module] 1 warning generated. Hello World: Scala Native!!! |
Или мы можем просто запустить его из командной строки напрямую:
1
2
3
4
|
$ pwd /Users/jos/dev/git/scala- native -clean/scala- native /helloworld- native /target/scala- 2.11 $ ./helloworldnative-out Hello World: Scala Native!!! |
Я надеюсь, что вы также можете начать с этого краткого вступления. Если позволит время, я планирую немного глубже погрузиться в родной язык scala и изучить некоторые его особенности.
Ссылка: | Начало работы с scala-native от нашего партнера JCG Йоса Дирксена в блоге Smart Java . |