Skip to content

Commit

Permalink
Fix #18: Add support for Scala Native (#19)
Browse files Browse the repository at this point in the history
* Full cross project with JVM supported

* Add support for Scala Native compiling

* Provide Scala Native as a cross project

* Replace Java Stack with Scala ArrayStack

* Remove Stack in PathBuilder

* Remove unused URLConnection import

* Add uTest and one testcase but don't run automatically

* Fix up scalaCrossVersions as recommended

* Add Metals and Bloop ignores

* Native tests compile, link, and work against modified version of Scala Native

* First changes to README to support new release.

* Update travis, update build and docs with new package

* Fix build.sbt after merge

* Aggregate sconfigNative in build

* Update scalafmt file with version for use with metals and other settings to match Scala Native

* Update copyright date

* Modify README and add users guide for Scala Native

* Fix README

* Changes for release 0.8.0 supporting Scala Native

* Fix formatting

* Add Linux build for Scala Native on Travis

* Bump sbt version
  • Loading branch information
ekrich committed Apr 23, 2019
1 parent 77c27e8 commit 0d9120b
Show file tree
Hide file tree
Showing 215 changed files with 241 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
.settings
.idea
.idea_modules
.metals/
.bloop/
/bin-test-lib
target/
/bin
Expand Down
3 changes: 3 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
version = 1.5.1
style = defaultWithAlign
docstrings = JavaDoc
assumeStandardLibraryStripMargin = true
project.git = true
13 changes: 9 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# use Docker-based container (instead of OpenVZ)
sudo: false
sudo: required

language: scala

Expand All @@ -9,6 +8,11 @@ jdk:
scala:
- 2.11.12

matrix:
include:
- os: linux
dist: trusty

stages:
- name: test
- name: release
Expand All @@ -19,7 +23,8 @@ jobs:
# stage="test" if no stage is specified
- env: TEST="scalafmt"
script: ./scripts/scalafmt --test
- env: TEST="test"
- env: TEST="linux"
before_install: ./scripts/travis-os-setup.sh
script: sbt +test doc
- stage: release
script: sbt ci-release
Expand All @@ -40,4 +45,4 @@ before_cache:
- rm -rf $HOME/.ivy2/local

before_install:
- git fetch --tags
- git fetch --tags
4 changes: 2 additions & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
_Copyright (c) 2011-2016 Typesafe Inc._<br/>
_Copyright (c) 2016-2018 Lightbend Inc. (formerly Typesafe Inc.)_<br/>
_Copyright (c) 2018 Eric K Richardson_
_Copyright (c) 2018-2019 Eric K Richardson_

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
Configuration library written in [Scala](https://www.scala-lang.org/) which is a direct translation
of the original widely used Java library.

Scala on the JVM is currently supported with the goal to add support for
[Scala Native](https://scala-native.readthedocs.io/), and [Scala.js](https://www.scala-js.org/).
Scala JVM and [Scala Native](https://scala-native.readthedocs.io/) are currently supported
with the goal to add support for [Scala.js](https://www.scala-js.org/).

For motivation and background about this project see the [PR](https://github.com/lightbend/config/pull/600)
to the original project.

Care has been taken to keep the API the same but changes are needed when moving from the Java API.
Using Java is also possible because the included Java examples work.
Using Java is also possible because the included Java examples work.

If you are looking for the original proven Java API, see
[https://github.com/lightbend/config](https://github.com/lightbend/config).
Expand All @@ -21,27 +21,35 @@ If you are looking for the original proven Java API, see
[![Maven Central](https://img.shields.io/maven-central/v/org.ekrich/sconfig_2.11.svg)](https://maven-badges.herokuapp.com/maven-central/org.ekrich/sconfig_2.11)

```scala
libraryDependencies += "org.ekrich" %% "sconfig" % "X.Y.Z"
libraryDependencies += "org.ekrich" %%% "sconfig" % "x.y.z"
```

To use in sbt, replace `X.Y.Z` with the version from Maven Central badge above.
To use in `sbt`, replace `x.y.z` with the version from Maven Central badge above.
All available versions can be seen at the [Maven Repository](https://mvnrepository.com/artifact/org.ekrich/sconfig).

## Usage and Help
[![Scaladoc](https://www.javadoc.io/badge/org.ekrich/sconfig_2.11.svg?label=scaladoc)](https://www.javadoc.io/doc/org.ekrich/sconfig_2.11)
[![Join chat https://gitter.im/ekrich/sconfig](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ekrich/sconfig?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

The following document copies are local to this repository but internal links may refer to the
original site documents via hyperlink.
original site documents via hyperlink. These are here as a snapshot when the library was ported
for reference purposes only. Refer to `config` library above to see the latest docs.

[Overview](docs/original/README.md) - A comprehensive guide to configuration.

[HOCON](docs/original/HOCON.md) - The HOCON Specification

The intent is to keep the library in sync with the original but each PR needs to be be ported
to maintain feature parity. Changes to support Scala Native and Scala.js may make this goal
unattainable in the future.

[Scala Native](docs/SCALA-NATIVE.md) - A guide to using Scala Native.

For specific changes, refer to the releases below.

## Versions

Release [0.8.0](https://github.com/ekrich/sconfig/releases/tag/v0.8.0) - (2019-04-23)<br/>
Release [0.7.6](https://github.com/ekrich/sconfig/releases/tag/v0.7.6) - (2019-04-10)<br/>
Release [0.7.5](https://github.com/ekrich/sconfig/releases/tag/v0.7.5) - (2019-04-05)<br/>
Release [0.7.0](https://github.com/ekrich/sconfig/releases/tag/v0.7.0) - (2018-12-14)
65 changes: 45 additions & 20 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// to release, bump major/minor/micro as appropriate,
// update NEWS, update version in README.md, tag, then
// publishSigned.
// Release tags should follow: http://semver.org/
// shadow sbt-scalajs' crossProject and CrossType until Scala.js 1.0.0 is released
import sbtcrossproject.CrossPlugin.autoImport.crossProject

addCommandAlias(
"run-examples",
Expand Down Expand Up @@ -60,8 +58,9 @@ ThisBuild / pomIncludeRepository := { _ =>

lazy val root = (project in file("."))
.aggregate(
testLib,
configLib,
testLibJVM,
sconfigJVM,
sconfigNative,
simpleLibScala,
simpleAppScala,
complexAppScala,
Expand All @@ -72,15 +71,17 @@ lazy val root = (project in file("."))
.settings(commonSettings)
.settings(
name := "sconfig-root",
crossScalaVersions := Nil,
doc / aggregate := false,
doc := (configLib / Compile / doc).value,
doc := (sconfigJVM / Compile / doc).value,
packageDoc / aggregate := false,
packageDoc := (configLib / Compile / packageDoc).value,
packageDoc := (sconfigJVM / Compile / packageDoc).value,
)

lazy val configLib = Project("sconfig", file("sconfig"))
.dependsOn(testLib % "test->test")
.settings(
lazy val sconfig = crossProject(JVMPlatform, NativePlatform)
.crossType(CrossType.Full)
//.jsSettings(/* ... */) // defined in sbt-scalajs-crossproject
.jvmSettings(
libraryDependencies += "io.crashbox" %% "spray-json" % "1.3.5-3" % Test,
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test,
Compile / compile / javacOptions ++= Seq("-source",
Expand All @@ -105,26 +106,50 @@ lazy val configLib = Project("sconfig", file("sconfig"))
mimaPreviousArtifacts := Set("org.ekrich" %% "sconfig" % prevVersion),
mimaBinaryIssueFilters ++= ignoredABIProblems
)
.nativeSettings(
nativeLinkStubs := true,
scalaVersion := scala211,
crossScalaVersions := List(scala211)
)

lazy val sconfigJVM = sconfig.jvm
.dependsOn(testLibJVM % "test->test")

lazy val sconfigNative = sconfig.native
.settings(
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.6.7" % Test,
testFrameworks += new TestFramework("utest.runner.Framework")
)

lazy val ignoredABIProblems = {
import com.typesafe.tools.mima.core._
import com.typesafe.tools.mima.core.ProblemFilters._
Seq(
exclude[Problem]("com.typesafe.config.impl.*")
exclude[Problem]("org.ekrich.config.impl.*")
)
}

lazy val commonSettings: Seq[Setting[_]] = Def.settings(
unpublished
)
lazy val commonSettings: Seq[Setting[_]] =
Def.settings(
skipPublish
)

def proj(id: String, base: File) =
Project(id, base) settings commonSettings

def proj(id: String, base: File) = Project(id, base) settings commonSettings
lazy val testLibJVM = testLib.jvm

lazy val testLib = proj("sconfig-test-lib", file("test-lib"))
lazy val testLib = crossProject(JVMPlatform)
.crossType(CrossType.Full)
.in(file("test-lib"))
.settings(
name := "sconfig-test-lib",
publish / skip := true
)

lazy val simpleLibScala = proj(
"sconfig-simple-lib-scala",
file("examples/scala/simple-lib")) dependsOn configLib
file("examples/scala/simple-lib")) dependsOn sconfigJVM
lazy val simpleAppScala = proj(
"sconfig-simple-app-scala",
file("examples/scala/simple-app")) dependsOn simpleLibScala
Expand All @@ -134,15 +159,15 @@ lazy val complexAppScala = proj(

lazy val simpleLibJava = proj(
"sconfig-simple-lib-java",
file("examples/java/simple-lib")) dependsOn configLib
file("examples/java/simple-lib")) dependsOn sconfigJVM
lazy val simpleAppJava = proj(
"sconfig-simple-app-java",
file("examples/java/simple-app")) dependsOn simpleLibJava
lazy val complexAppJava = proj(
"sconfig-complex-app-java",
file("examples/java/complex-app")) dependsOn simpleLibJava

val unpublished = Seq(
val skipPublish = Seq(
// no artifacts in this project
publishArtifact := false,
// make-pom has a more specific publishArtifact setting already
Expand Down
56 changes: 56 additions & 0 deletions docs/SCALA-NATIVE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Scala Native Help

Scala Native support has been added so [scalafmt](https://scalameta.org/scalafmt/) can
become a native application. The release has minimal capabilities at this time so
the following is an example of how to use the API.

## Read from String example

This assumes that you read a file into a `configStr` first.

```scala
val configStr =
"""
|maxColumn = 100
|project.git=true
|align = none
|danglingParentheses = true
|newlines.neverBeforeJsNative = true
|newlines.sometimesBeforeColonInMethodReturnType = false
|assumeStandardLibraryStripMargin = true
""".stripMargin

val conf = ConfigFactory.parseString(configStr)

val maxCol = conf.getInt("maxColumn")
val isGit = conf.getBoolean("project.git")
```

### How to read a HOCON configuation file into a String

In order to read the configuration file into a `String` you need to know the relative
path from where the executable was started or use an absolute path. If the
Scala Native executable is `run` from `sbt` it will have the current working directory
equal to the directory at the base of your project where `sbt` was started. If curious
or the situation is unclear you can run the following code inside your Scala Native
application to find the path.

```scala
val dir = System.getProperty("user.dir")
println(s"Dir: $dir")
```

Continuing the same thought process you can use the following code to read the file
into a `String` from a simple `sbt` project where the `src` directory is at the top
level of your project.

```scala
import java.nio.file.{Files, Paths}
val bytes = Files.readAllBytes(Paths.get("src/main/resources/myapp.conf"))
val configStr = new String(bytes)
```

Using this code with the code above gives you a working solution to use `sconfig`
with Scala Native.

[Back to README](../README.md)
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.2.7
sbt.version=1.2.8
5 changes: 4 additions & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// includes sbt-dynver sbt-pgp sbt-sonatype sbt-git
addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.2.1")
addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.2.6")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.3.0")
// for Scala Native support
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "0.6.0")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.3.9")
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.ekrich.config.Optional

/**
* Internal implementation detail, not ABI stable, do not touch.
* For use only by the {@link com.typesafe.config} package.
* For use only by the {@link org.ekrich.config} package.
*/
object ConfigBeanImpl {

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -778,25 +778,23 @@ class ConfigSubstitutionTest extends TestUtils {
resolved.getIntList("x.y.ptrToPtrToArr").asScala)
}

private val substSystemPropsObject = {
private val substSystemPropsObject =
parseObject("""
{
"a" : ${configtest.a},
"b" : ${configtest.b}
}
""")
}
{
"a" : ${configtest.a},
"b" : ${configtest.b}
}
""")

@Test
def doNotSerializeUnresolvedObject(): Unit = {
def doNotSerializeUnresolvedObject(): Unit =
checkNotSerializable(substComplexObject)
}

@Test
def resolveListFromSystemProps(): Unit = {
val props = parseObject("""
|"a": ${testList}
""".stripMargin)
|"a": ${testList}
""".stripMargin)

System.setProperty("testList.0", "0")
System.setProperty("testList.1", "1")
Expand All @@ -815,8 +813,8 @@ class ConfigSubstitutionTest extends TestUtils {
@Test
def resolveListFromEnvVars(): Unit = {
val props = parseObject("""
|"a": ${testList}
""".stripMargin)
|"a": ${testList}
""".stripMargin)

//"testList.0" and "testList.1" are defined as envVars in build.sbt
val resolved = resolve(props)
Expand Down
Loading

0 comments on commit 0d9120b

Please sign in to comment.