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
Fix #657: Give libraries a way to include native C code to be compiled. #1637
Conversation
I have removed the WIP as this could probably use some review or discussion at this point. Here are some highlights of the implementation.
The changes deprecate |
Now, directory C/C++/S files are hashed to avoid a copy when they have not changed. This is similar to when a jar doesn't change, it is not unpacked. Computing the hash of the |
Ready for Review. |
Given an interest in #155, this does allow a new class of libraries that were not possible before without hacking. This PR allows you to distribute a pure Scala Native library that can include C/C++/S code in a standard jar format exactly how the Scala Native My test case library is stensorflow which is currently just a Scala Native C binding with no high level Scala code. It is The PR above still uses the standard static link setup but does allow the full Scala Native optimization system to work on any application or library (with tests or examples to force a link) for the library of interest. It is very easy to use in a natural way with the current Scala Native plugin or raw tool chain. |
@densh What the current plan about it? It is very useful change |
I have been thinking about this PR and I think it might be helpful to put the native code in a directory specified by the full org and project name to have a unique namespace. So instead of |
@lolgab I added namespaces based on the organization and project name in the last commit. |
5928035
to
9dfa8a0
Compare
RecapAllow internal Scala Native components and external libraries to include C code which will be compiled on demand by the Scala Native plugin. Vision of the futureRather than Scala Native be a platform where everything is included, this opens up the potential where Scala Native can consist of components that are included from the repository based on the platform or potentially some future configuration. This could help us make Scala Native scale from smaller devices and different platforms, other than Linux/UNIX, to more enterprise usages. Some examples follow:
We still want to support Java libraries like we do now to promote a robust set of portable cross projects. This is a change that can allow an evolution of the platform guided by the leadership of this project and the needs and contributions from the community. I know there has been some frustration especially related to Windows support as the requested changes would have been too disruptive and potentially destabilizing. This should allow some of the development to run in parallel in separate projects that will not affect the stability of the current system. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My experience with Scala.js is that we shouldn't bake support for platform dependencies in the main sbt plugin. We did it with jsDependencies
in Scala.js and it was a nightmare. It was never really correct, and could never be fixed. We ended up moving it to a separate sbt plugin.
Can we implement compiling C code in a separate sbt plugin? If yes, that should be the way to go. If not, what prevents us from doing so? Is there a minimal set of hooks that we can to sbt-scala-native that would allow to implement this in a separate plugin?
Looking at This really is not about compiling C per se. If you are building an application and you can't really create an Scala Native interface to C with Compiling C is already baked into the I'm not sure if this helps explain or answers you questions exactly. I do think something other than this solution is going to be a much bigger development project. I tried to minimize the complexity/changes and put only what needs to be put in the plugin and putting the rest into the I am really not sure about how @rwhaling @lolgab Could you take a look and see what you think about this change and approach? |
A bit late to the discussion, but the strategy for searching the entire classpath is actually implemented in my fork for 32-bit support + JNI bridging (see shadaj@6888706). To ensure unique folder names, I just used the name of the JAR file the sources were extracted from. Then, any library just needs to add C sources they need with a extra module dependency (https://github.com/Team846/scala-native-wpilib/blob/master/scalaNativeJNINativeLib/src/main/resources/mockjni.cpp). While not a large-scale usage of the feature, since we only had one externally provided C source, this strategy seemed to work pretty well since there were no changes needed to projects using these extra C sources as they were automatically brought into the classpath by regular dependency resolution. |
This looks like you used |
I think this is the root problem that needs to be solved. We need to make Scala Native able to directly interface with any C library. It needs perfect interop. I managed to do that for Scala.js with a perfect interop with JS, and interop with JS is fundamentally much more complex than interop with C, so I'm pretty confident we can achieve perfect interop for C. |
I agree that "perfect interopt" is the ultimate solution but I don't think that is the only issue this is solving.
The issues are probably not low hanging fruit otherwise @densh would have probably had a solution.
I know we should carefully look at these changes and make sure we get the best solution we can based on current and future needs. Perhaps others can help provide some guidance and feedback on this PR as well. |
Splitting the projects with their own C code. |
@sjrd I now just use the |
… header files to determine changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK let's merge this as is. But I'd like to see a follow up PR, as you suggested, to only take files in some specified subdirectory (and therefore move the files in the nativelib to match).
…o be compiled. (scala-native#1637) Previously, C source files in the nativelib's jar (i.e., in its resources), where compiled and linked together with the Scala Native-emitted code. That behavior was reserved for the nativelib, and not applied to user-defined libraries. This commit generalizes this support to all libraries. Native code source files present anywhere on the classpath will be compiled and linked together in the final executables. This allows libraries to include native code in their distribution. A followup commit should restrict the set of included files to one specific subdirectory of the classpath entries, in order to allow libraries to also distribute source files in their actual resources for other purposes.
Currently, C or C++ code added into the
resources
directory is used by Scala Nativenativelib
. The basic need for adding C code to a library is to support C macros and any adapter functions for C libraries that passstruct
s by value. Adding the raw C is portable and a good solution. I have two use cases I am targeting at this time.resources
which gets copied to the root of the jar archive. Thenativelib
and any addednativeLibraryDependencies
, a new plugin setting, are unpacked and compiled as part of the application.Currently, you also must add toEdit: This was incorrect as Scala Native keeps track and adds these to the link phase.nativeLinkingOptions
for each library to link.The
Config
class contains a deprecation and also a runtime deprecation warning as 3rd party tools such ascoursier
may need some minor changes to allow this feature to work. We may need to deprecate and refactor some of the other publictools
APIs as well depending on need.nativeCodeInclude
which is false by default. The intent is to combine any native code to the compile and link sequence when set totrue
. This way the currentpublishLocal
methodology will continue to function without change.There are quite a few other ideas in the issue but I think these 2 items are a good start and enable libraries and local coding without local changes to the build system.
Edit: 2019-07-19
This conceivable allows Scala Native to distribute
clib
orposixlib
as separate artifacts if the code is not used injavalib
or other core parts of the system.