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 Scala Native Examples #3657

Merged
merged 54 commits into from
Oct 31, 2024
Merged

Conversation

c0d33ngr
Copy link
Contributor

@c0d33ngr c0d33ngr commented Oct 3, 2024

This is a PR to close issue #3647

@c0d33ngr c0d33ngr marked this pull request as draft October 3, 2024 09:16
@c0d33ngr
Copy link
Contributor Author

c0d33ngr commented Oct 3, 2024

Hi @lihaoyi something like this or I have to use scalatags and mainargs?

@lihaoyi
Copy link
Member

lihaoyi commented Oct 3, 2024

Let's use the same scalatags/mainargs example as we did in scalalib/basic/1-simple/.

You can get rid of most of the docs that are already part of scalalib/basic/1-simple/. The point of this page is to show what's unique about scala native, so the docs should highlight the differences and unique features of it: e.g. the compile to binary, the different optimization levels, etc.

@c0d33ngr
Copy link
Contributor Author

c0d33ngr commented Oct 3, 2024

Alright, it's noted

@c0d33ngr c0d33ngr changed the title Add scalanative doc for 1-simple Draft to add scalanative doc Oct 3, 2024
@c0d33ngr
Copy link
Contributor Author

c0d33ngr commented Oct 4, 2024

//build.mill
package build
import mill._, scalalib._, scalanativelib._

object `package` extends RootModule with ScalaNativeModule {
  def scalaVersion = "2.13.11"
  def scalaNativeVersion = "0.5.5"
  def nativeLinkingOptions = pathToWhereTheTargetWasSaved

  object test extends ScalaNativeTests {
    def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4")
    def testFramework = "utest.runner.Framework"
  }
}
#makefile
all : 
	gcc -m64 -shared -c native-src/HelloWorld.c -o target/libstub.so

@lihaoyi good day, I've some few questions to ask

Is it possible for me to run the commands in makefile from build.mill config?
Also how get the full file path of where am currently working in?

When I replace the def nativeLinkingOptions with the full path to the choice location to store the .so file, it worked. But before that I had to run make from terminal to generate the .so file in the location

That's why I asked whether it's possible to run the comments in makefile from build.mill

Lastly, is this what you want for the 2-interop code example?

@lihaoyi
Copy link
Member

lihaoyi commented Oct 4, 2024

Is it possible for me to run the commands in makefile from build.mill config?

Sure, os.call(("make, "blah")). Though I suggest if you know what you want to call, you can os.call gcc directly rather than going through make

Also how get the full file path of where am currently working in?

T.dest or millSourcePath depending on what where am currently working in means

When I replace the def nativeLinkingOptions with the full path to the choice location to store the .so file, it worked. But before that I had to run make from terminal to generate the .so file in the location

Make an upstream task generate the SO file and return a PathRef for the downstream task to consume

Lastly, is this what you want for the 2-interop code example?

Yes the 2-interop example looks great. Perhaps let's make it return a value as well, so rather than printString we make it reverseString or something, just so people can see how that works? Other than that it looks great: a tiny C program, a tiny Scala facade, and a tiny Scala program all interacting. You just need to wire up gcc to compile the thing as part of Mill so we can avoid having to run make manually

@c0d33ngr c0d33ngr changed the title Draft to add scalanative doc Add Scala Native Examples Oct 4, 2024
@c0d33ngr
Copy link
Contributor Author

@lihaoyi what you think

@c0d33ngr c0d33ngr marked this pull request as ready for review October 29, 2024 08:51
@c0d33ngr c0d33ngr changed the title [WIP] Add Scala Native Examples Add Scala Native Examples Oct 29, 2024
Copy link
Member

@lihaoyi lihaoyi left a comment

Choose a reason for hiding this comment

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

Took another pass at reviewing this. I think we're getting there! There's still some changes necessary, but it's already in a much better state than it was before

example/scalalib/native/1-simple/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/1-simple/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/1-simple/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/1-simple/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/2-interop/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/2-interop/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/4-common-config/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/3-multi-module/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/2-interop/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/1-simple/build.mill Outdated Show resolved Hide resolved
@c0d33ngr
Copy link
Contributor Author

@lihaoyi I've done the changes

@lihaoyi
Copy link
Member

lihaoyi commented Oct 29, 2024

@lolgab could you take a pass at reviewing this? Since you have much more experience with scala native than I do

@lihaoyi lihaoyi requested a review from lolgab October 29, 2024 22:27
Copy link
Member

@lolgab lolgab left a comment

Choose a reason for hiding this comment

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

Gave a quick look and found some possible improvements

example/scalalib/native/4-common-config/build.mill Outdated Show resolved Hide resolved
example/scalalib/native/4-common-config/build.mill Outdated Show resolved Hide resolved
Comment on lines 9 to 16
def generateHtml(text: String): CString = {
val colored = Console.RED + "<h1>" + text + "</h1>" + Console.RESET

implicit val z: Zone = Zone.open
val cResult = toCString(colored)
z.close()
cResult
}
Copy link
Member

Choose a reason for hiding this comment

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

What is the point of this code?
it seems just scala code converted to C and also used after free. You can't use the CString after closing the Zone.
A better example would be using an open source html templating c library and then convert the C result to a Scala string

Copy link
Member

Choose a reason for hiding this comment

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

It was meant to be a strawman hello-world Scala-Native application, so intentionally overly simple. Is it easy to integrate open source C libraries into scala native? I've never done it before

@lihaoyi
Copy link
Member

lihaoyi commented Oct 30, 2024

Thanks @lolgab!

@c0d33ngr if we can just pass in the C sources via resources/scala-native, do we still need def nativeSources to reference them explicitly? Or would it suffice just to let scala-native pick them up from the resource path?

I think for the suggestion to add a third-party C library to use in the example, let's leave that to a follow-up bounty/PR, since it's a bit out of scope of the original ticket that was intentionally pretty minimal #3647

@c0d33ngr
Copy link
Contributor Author

c0d33ngr commented Oct 30, 2024

Thanks @lolgab!

@c0d33ngr if we can just pass in the C sources via resources/scala-native, do we still need def nativeSources to reference them explicitly? Or would it suffice just to let scala-native pick them up from the resource path?

I think for the suggestion to add a third-party C library to use in the example, let's leave that to a follow-up bounty/PR, since it's a bit out of scope of the original ticket that was intentionally pretty minimal #3647

@lolgab is so right!! As long as the C codes are in resources/scala-native, Scala Native will detect them so there's no need for compiling them within a task. I resolved most of the changes he suggested

@c0d33ngr
Copy link
Contributor Author

Any more changes needed @lihaoyi ?

Copy link
Member

@lihaoyi lihaoyi left a comment

Choose a reason for hiding this comment

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

One nit and then I think we're good, @c0d33ngr once you fix the merge conflicts and we get a green CI run I'll merge this and close out the bounty

@c0d33ngr
Copy link
Contributor Author

One nit and then I think we're good, @c0d33ngr once you fix the merge conflicts and we get a green CI run I'll merge this and close out the bounty

Alright.. It's all greeny

At first, it wasn't but all of a sudden it restarted and ran successfully. Thought, the errors doesn't seem to be about scala-native examples

@lihaoyi lihaoyi merged commit cddb8f0 into com-lihaoyi:main Oct 31, 2024
24 checks passed
@lihaoyi
Copy link
Member

lihaoyi commented Oct 31, 2024

@c0d33ngr just a flaky test, not related to your PR. Thanks again for your efforts!

Email me your international bank transfer details and I will close out the bounty

@lefou lefou added this to the 0.12.2 milestone Oct 31, 2024

implicit val z: Zone = Zone.open()
val cResult = toCString(html)
cResult

Choose a reason for hiding this comment

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

Doesn't cResult escape here the Zone where it was allocated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright... Noted

I'm into it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

1-simple/src/Foo.scala

object Foo {
  
  def generateHtml(text: String) (using Zone) = {
    val html = "<h1>" + text + "</h1>\n"

    val cResult = toCString(html)
    cResult
  
  }

  @main
  def main(text: String) = Zone {
    stdio.printf(generateHtml(text))
  }
...

3-multi-module/foo/src/Foo.scala

...
object Foo {
  @main
  def main(@arg(name = "foo-text") fooText: String,
           @arg(name = "bar-text") barText: String): Unit = Zone {

    val cFooText = toCString(fooText)
    val cBarText = toCString(barText)

...

3-multi-module/bar/src/Bar.scala

...
object Bar {
  def main(args: Array[String]): Unit = Zone {
    println("Running HelloWorld function")
    val result = toCString(args(0))
    val barValue = HelloWorldBar.stringLength(result)
...

4-common-config/src/Foo.scala

...
object Foo {

  def generateHtml(text: String) (using Zone) = {
    val colored = Console.RED + "<h1>" + text + "</h1>" + Console.RESET

    val cResult = toCString(colored)
    cResult
  }
  
  def main(args: Array[String]): Unit = Zone {
    val value = generateHtml("hello")
    stdio.printf(c"Foo.value: %s\n", value)
  }
}

Hello @sideeffffect Here's is the updated code. Are they good to go?
Also please do a review on the scala-native codes I wrote just in case there are some changes needed to be made. It came to my notice that doc should be as good it can be cause future readers would depend on it

Copy link
Member

Choose a reason for hiding this comment

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

@c0d33ngr please open a new PR with these changes, it's easier to discuss individual code changes on the PR, and when we're done we can just click the merge button :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants