bytedeco / gradle-javacpp Goto Github PK
View Code? Open in Web Editor NEWGradle plugins to automate the build process of JavaCPP and JavaCV
License: Other
Gradle plugins to automate the build process of JavaCPP and JavaCV
License: Other
In an effort to separate our main business logic from javacpp, I've setup our project using gradle's multi-module support with a structure like so
src/
business-logic/ # rest controllers and other business logic that call the interface
javacpp-interface/ # Single class with interface methods
javacpp-implementation # implements the interface
Both the business-logic and javacpp-implementation modules have a dependency on javacpp-interface. This will allow us to write unit tests in the business-logic layer without relying on javacpp code(We develop on windows but the C++ library is targeting linux in a docker image).
What I'm running into issues with is that the implementation class fails to compile as it cannot see the interface class in the javacpp-interface. We end up receiving class loader issues like such:
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Execution failed for task ':javacpp-implementation:javacppBuildParser'.
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] > com/my-org/ndi/javacpp/impl/INativeNdiService
Unable to load class 'com.my-org.ndi.javacpp.impl.INativeNdiService'.
Both the interface and the implementation are in the same package structure, but different modules.
My gradle file looks something like this(Note we are using the latest version 1.5.8 that's stored in a gradle catalog):
plugins {
id 'java-library'
alias(libs.plugins.bytedeco.javacpp.build)
alias(libs.plugins.bytedeco.javacpp.platform)
alias(libs.plugins.springboot)
alias(libs.plugins.dependencyManagement)
}
javacppCompileJava {
include 'com/my-org/ndi/javacpp/impl/*'
}
dependencies {
implementation project(":javacpp-interface")
implementation libs.bytedeco
}
Hi
I try to fetch a "String" from a C function with char * signature, using BytePointer in JavaCPP.
However when I call the getString method, it returns the string with length of allocated size, instead of using the '\0' position.
scala code below:
val deviceName = new BytePointer(1000L)
deviceName.fill(0)
cuDeviceGetName(deviceName, 1000, device.get())
println("device name: " + deviceName.getString("utf-8"))
println("str len: ", deviceName.getString("utf-8").length)
You'll find the last line prints out
(str len: ,1000)
Hi,
with gradle 8.x, loading the plugin version 1.5.9 fails with
Failed to apply plugin 'org.bytedeco.gradle-javacpp-build'.
Could not create task ':cavis-native:cavis-native-lib:javacppCompileJava'.
> 'java.io.File org.gradle.api.file.SourceDirectorySet.getOutputDir()'
The reason is, that getOutputDir() has been replaced with getClassesDirectory
gradle/gradle@aeb4e00#diff-e6ac06306676ba80c5ed481c54208dfb7cf3ade725900705537fa38a3ee426f9
Stacktrace:
Caused by: org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreationException: Could not create task ':cavis-native:cavis-native-lib:javacppCompileJava'.
at org.gradle.api.internal.tasks.DefaultTaskContainer.taskCreationException(DefaultTaskContainer.java:721)
at org.gradle.api.internal.tasks.DefaultTaskContainer.access$600(DefaultTaskContainer.java:77)
at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider.domainObjectCreationException(DefaultTaskContainer.java:713)
at org.gradle.api.internal.DefaultNamedDomainObjectCollection$AbstractDomainObjectCreatingProvider.tryCreate(DefaultNamedDomainObjectCollection.java:948)
at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider.access$1401(DefaultTaskContainer.java:660)
at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider$1.run(DefaultTaskContainer.java:686)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider.tryCreate(DefaultTaskContainer.java:682)
at ...snipp...Caused by: java.lang.NoSuchMethodError: 'java.io.File org.gradle.api.file.SourceDirectorySet.getOutputDir()'
at org.bytedeco.gradle.javacpp.BuildPlugin$1$2.execute(BuildPlugin.java:134) <----- HERE
at org.bytedeco.gradle.javacpp.BuildPlugin$1$2.execute(BuildPlugin.java:131)
at org.gradle.api.internal.DefaultMutationGuard$1.execute(DefaultMutationGuard.java:45)
at org.gradle.api.internal.DefaultMutationGuard$1.execute(DefaultMutationGuard.java:45)
at ...snipp...
Hi,
gradle fails to build java code, when the gradle-javacpp plugin is added. It looks liek javacppCompileJava is not working correctly.
Example gradle.build
plugins {
id 'java-library'
id 'org.bytedeco.gradle-javacpp-build' version "1.5.5"
}
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
}
Example java code like:
import lombok.val;
public class Bla {
void example() {
val something = somedatatype;
}
}
Error message during gradle build:
example:
error: incompatible types: org.nd4j.linalg.api.ndarray.INDArray cannot be converted to lombok.val
val fA = A.castTo(DataType.FLOAT);
The problem goes away, when the gradle-javacpp plugin is removed from gradle.build
Thanks
Brian
Is there any way to prevent the BuildTask.buildCommand
from running either programatically or through the environment? Sorts of like the property javacpp.cppbuild.skip
for the Maven builds?
I tried to enable BuildTask.skip
but it does not look like the plugin respects this option. As far as I can tell, the BuildPlugin doesn't ever use the property anyways so it's just hanging there, unused.
Assuming that BuildTask.skip
is the equivalent of the aforementioned cppbuild.skip
, I have submitted a patch to junlarsen@f2653dc which I can PR in.
I tried to use the plugin with kotlin dsl but it doesn't like to work. I get errors like this:
$ ../../gradlew check
FAILURE: Build failed with an exception.
* Where:
Build file '/tmp/gradle-javacpp/samples/javacv-demo-kotlindsl/build.gradle.kts' line: 7
* What went wrong:
Plugin [id: 'org.bytedeco.gradle-javacpp-platform', version: '1.5.4-SNAPSHOT'] was not found in any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Plugin Repositories (could not resolve plugin artifact 'org.bytedeco.gradle-javacpp-platform:org.bytedeco.gradle-javacpp-platform.gradle.plugin:1.5.4-SNAPSHOT')
Searched in the following repositories:
Gradle Central Plugin Repository
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
Everything works fine with groovy. Any ideas?
I am attempting to generate JNI code inside a gradle multi-project build.
The directory structure is as follows:
/JavaCpp
-> /API
-> /Impl
The /Impl subproject contains the cpp header files and JavaCpp annotations required for generating the JNI .so library. It also contains two Java files MyClass.java and Delegate.java.
Inside the Impl subproject:
public class MyClass implements MyInterface {
private final Delegate delegate;
@Override
public boolean function() {
return delegate.function()
}
@Platform(include = "/lib/process.h", link="process")
public class Delegate {
@Function()
public native boolean function();
The API subproject contains a Java interface that describes the functions the JNI code implements.
Inside the API subproject:
public interface MyInterface {
boolean function();
During the :Impl:javacppBuildParser task, I'm getting the following error:
Execution failed for task ':Impl:javacppBuildParser'.
#18 21.53 > com/package/MyInterface (wrong name: API/build/classes/java/main/com/package/MyInterface)
Is there some way I can prevent this class from being scanned by JavaCpp? It is not needed during the JavaCpp building since all of the JavaCpp annotations are being applied to the Delegate
class.
I want use macosx-x86_64
on run application, but use linux-x86_64
when package.
These way seems not working.
parent?.ext?.set("javacppPlatform", "linux-x86_64")
println(parent?.ext?.get("javacppPlatform"))
implementation(group = "org.bytedeco", name = "javacpp")
implementation(group = "org.bytedeco", name = "ffmpeg-platform")
implementation(group = "org.bytedeco", name = "javacv")
or
tasks {
"war"(War::class) {
first {
parent?.ext?.set("javacppPlatform", "linux-x86_64")
println(parent?.ext?.get("javacppPlatform"))
true
}
enabled = true
}
}
I've found this extremely useful, but upgrading to Gradle 7.6 today resulted in a large number of messages
Could not get the classifier of org.bytedeco:javacpp:1.5.8: java.lang.NoSuchMethodException: org.gradle.api.internal.artifacts.repositories.resolver.AbstractDependencyMetadataAdapter.getOriginalMetadata()
and jars for all the platforms being downloaded.
As far as I can tell, the problem is that AbstractDependencyMetadataAdapter.getOriginalMetadata()
was removed in this commit: gradle/gradle@ad1cc1c
The good news (I hope) is that there's now a public AbstractDependencyMetadataAdapter.getMetadata()
.
Hi,
I am trying to use the plugin to execute an arbitrary shell command and leverage its caching function.
plugins {
id 'java-library'
id 'org.bytedeco.gradle-javacpp-build' version "1.5.5"
}
javacppBuildCommand {
buildCommand = ['sh', 'something.sh']
}
Issues:
How to achieve, that dependencies are downloaded and extracted into the javacpp cache folder?
I tried to include dependencies as api, implementation and javacppPlatform without luck. Also referencing included classes as linkResources, includeResources or buildResource, did not make the difference.
How to pass environment variables set by the javacpp Builder to either the shell script called or have them set in the system environment? I.e. Builder is setting BUILD_DIR, that does not come through?
Thanks
Brian
I am refrencing gradle-javacpp-android to use javacpp with android studio. After a bit adjust to gradle-javacpp-android
, it successfully generated NativeLibrary
. But jnijavacpp.cpp
and jniNativeLibrary.cpp
are not generated.
plugins {
id 'com.android.application'
id 'org.bytedeco.gradle-javacpp-build' version '1.5.7'
}
allprojects {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked"
}
}
android {
compileSdkVersion 32
defaultConfig {
applicationId "com.example.myapplication"
minSdkVersion 28
targetSdkVersion 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.18.1"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
ndkVersion '25.1.8937393'
buildToolsVersion '33.0.0'
}
android.applicationVariants.all { variant ->
def variantName = variant.name.capitalize() // either "Debug" or "Release"
def javaCompile = project.tasks.getByName("compile${variantName}JavaWithJavac")
def generateJson = project.tasks.getByName("generateJsonModel$variantName")
// Compiles NativeLibraryConfig.java
task "javacppCompileJava$variantName"(type: JavaCompile) {
include 'com/example/myapplication/NativeLibraryConfig.java'
source = javaCompile.source
classpath = javaCompile.classpath
destinationDir = javaCompile.destinationDir
doLast{
println "Hello World javacppCompileJava"
}
}
// Parses NativeLibrary.h and outputs NativeLibrary.java
task "javacppBuildParser$variantName"(type: org.bytedeco.gradle.javacpp.BuildTask) {
dependsOn "javacppCompileJava$variantName"
classPath = [javaCompile.destinationDir]
includePath = ["$projectDir/src/main/cpp/"]
classOrPackageNames = ['com.example.myapplication.NativeLibraryConfig']
outputDirectory = file("$projectDir/src/main/java/")
doLast{
println "Hello World javacppBuildParser"
}
}
// Compiles NativeLibrary.java and everything else
javaCompile.dependsOn "javacppBuildParser$variantName"
// Generates jnijavacpp.cpp and jniNativeLibrary.cpp
task "javacppBuildCompiler$variantName"(type: org.bytedeco.gradle.javacpp.BuildTask) {
dependsOn javaCompile
classPath = [javaCompile.destinationDir]
classOrPackageNames = ['com.example.myapplication.NativeLibrary']
compile = true
deleteJniFiles = false
outputDirectory = file("$projectDir/src/main/cpp/")
doLast{
println "Hello World javacppBuildCompiler"
}
}
// Picks up the C++ files listed in CMakeLists.txt
generateJson.dependsOn "javacppBuildCompiler$variantName"
}
dependencies {
implementation 'org.bytedeco:javacpp:1.5.7'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
hi~ Is there an example of Android?
Trying with latest Gradle...
javacppBuildCommand {
// typically set here the buildCommand to the script that fills up includePath and linkPath
}
javacppBuildParser {
// typically set here the classOrPackageNames to class names implementing InfoMap
}
javacppBuildCompiler {
// typically set here boolean flags like copyLibs
}
tasks.withType(org.bytedeco.gradle.javacpp.BuildTask) {
// set here default values for all build tasks below, typically just includePath and linkPath,
// but also properties to set the path to the NDK and its compiler in the case of Android
generate = true;
compile = false;
outputDirectory = new File("src/main/cpp");
}
Result:
> Task :javacppBuildParser FAILED
Execution optimizations have been disabled for task ':javacppBuildParser' to ensure correctness due to the following reasons:
- Additional action of task ':javacppBuildParser' was implemented by the Java lambda 'org.bytedeco.gradle.javacpp.BuildPlugin$$Lambda$814/0x00000008012f1af0'. Reason: Using Java lambdas is not supported as task inputs. Please refer to https://docs.gradle.org/7.4/userguide/validation_problems.html#implementation_unknown for more details about this problem.
Execution failed for task ':javacppBuildParser'.
> net/fabricmc/api/ModInitializer
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
It appears that the javacppPlatform
property is ignored. No matter what I write, all I get is the linux-x86_64 libs (when I really want arm libs, too)
plugins {
id "org.jetbrains.kotlin.jvm" version "1.4.10"
id "application"
id 'org.bytedeco.gradle-javacpp-platform' version "1.5.4"
}
ext {
javacppPlatform = 'linux-arm'
}
group "rover"
version "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
mainClassName = "MainKt"
dependencies {
testImplementation group: "junit", name: "junit", version: "4.12"
compile "org.jetbrains.kotlin:kotlin-stdlib"
compile group: "com.pi4j", name: "pi4j-gpio-extension", version: "1.2"
compile group: "org.bytedeco", name: "javacv", version: "1.5.4"
compile 'org.bytedeco:opencv-platform:4.4.0-1.5.4'
}
I'm not sure if this issue should be put here or in https://github.com/bytedeco/sample-projects, sorry if I misplace it.
So, the current example for Android uses com.android.tools.build:gradle:4.1.1
and it builds fine, but when I update the Android plugin to 7.1.3
, the project won't build complaining that jniNativeLibrary.cpp
and jnijavacpp.cpp
cannot be found:
Build command failed.
Error while executing process C:\Users\<my username>\AppData\Local\Android\Sdk\cmake\3.10.2.4988404\bin\ninja.exe with arguments {-C <my project path>\gradle-javacpp-android\app\.cxx\Debug\3n4fu1n1\arm64-v8a native-lib}
ninja: Entering directory `<my project path>\gradle-javacpp-android\app\.cxx\Debug\3n4fu1n1\arm64-v8a'
[1/3] Building CXX object CMakeFiles/native-lib.dir/jniNativeLibrary.cpp.o
FAILED: CMakeFiles/native-lib.dir/jniNativeLibrary.cpp.o
C:\Users\<my username>\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android21 --gcc-toolchain=C:/Users/<my username>/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/<my username>/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/sysroot -Dnative_lib_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O0 -fno-limit-debug-info -fPIC -MD -MT CMakeFiles/native-lib.dir/jniNativeLibrary.cpp.o -MF CMakeFiles\native-lib.dir\jniNativeLibrary.cpp.o.d -o CMakeFiles/native-lib.dir/jniNativeLibrary.cpp.o -c <my project path>/gradle-javacpp-android/app/src/main/cpp/jniNativeLibrary.cpp
clang++: error: no such file or directory: '<my project path>/gradle-javacpp-android/app/src/main/cpp/jniNativeLibrary.cpp'
clang++: error: no input files
[2/3] Building CXX object CMakeFiles/native-lib.dir/jnijavacpp.cpp.o
FAILED: CMakeFiles/native-lib.dir/jnijavacpp.cpp.o
C:\Users\<my username>\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android21 --gcc-toolchain=C:/Users/<my username>/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/<my username>/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/sysroot -Dnative_lib_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O0 -fno-limit-debug-info -fPIC -MD -MT CMakeFiles/native-lib.dir/jnijavacpp.cpp.o -MF CMakeFiles\native-lib.dir\jnijavacpp.cpp.o.d -o CMakeFiles/native-lib.dir/jnijavacpp.cpp.o -c <my project path>/gradle-javacpp-android/app/src/main/cpp/jnijavacpp.cpp
clang++: error: no such file or directory: '<my project path>/gradle-javacpp-android/app/src/main/cpp/jnijavacpp.cpp'
clang++: error: no input files
ninja: build stopped: subcommand failed.
And indeed jniNativeLibrary.cpp
and jnijavacpp.cpp
are not built. I figure that probably JavaCpp tasks dependencies need to be changed in app/build.gradle
, but I'm struggling to do it on my own. Can you please update the example project?
I am trying to use this plugin in Android gradle. my gradle code is as follows:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'org.bytedeco.gradle-javacpp-platform' version "1.5.9"
}
android {
....
}
configurations {
javacpp
}
task javacppExtract(type: Copy) {
dependsOn configurations.javacpp
from { configurations.javacpp.collect { zipTree(it) } }
include "lib/**"
into "$buildDir/javacpp/"
android.sourceSets.main.jniLibs.srcDirs += ["$buildDir/javacpp/lib/"]
tasks.getByName('preBuild').dependsOn javacppExtract
}
dependencies {
......
def javacppVersion = '1.5.9'
def ffmpegVersion = '6.0'
implementation group: 'org.bytedeco', name: 'javacv', version: "$javacppVersion"
javacpp group: 'org.bytedeco', name: 'ffmpeg-platform', version: "$ffmpegVersion-$javacppVersion"
}
I build the project successfully but when i reach the FFmpeg code which is like this (I think the code does not matter):
// Open the MP3 file
val formatContext = AVFormatContext(null)
if (avformat.avformat_open_input(formatContext, mp3FilePath, null, null) != 0) {
println("Could not open the input file")
return
}
...
....
And this gives the following runtime error :
java.lang.UnsatisfiedLinkError: dlopen failed: library "libjniavutil.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:1077)
at java.lang.Runtime.loadLibrary0(Runtime.java:998)
at java.lang.System.loadLibrary(System.java:1661)
at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1832)
at org.bytedeco.javacpp.Loader.load(Loader.java:1423)
at org.bytedeco.javacpp.Loader.load(Loader.java:1234)
at org.bytedeco.javacpp.Loader.load(Loader.java:1210)
at org.bytedeco.ffmpeg.global.avutil.<clinit>(avutil.java:14)
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:454)
at org.bytedeco.javacpp.Loader.load(Loader.java:1289)
at org.bytedeco.javacpp.Loader.load(Loader.java:1234)
at org.bytedeco.javacpp.Loader.load(Loader.java:1210)
at org.bytedeco.ffmpeg.avformat.AVFormatContext.<clinit>(AVFormatContext.java:36)
getLibsDir
was deprecated in 6.x and removed in 7.x
Hi,
I have a problem with generating ./gradlew from gradle wrapper.
installed gradle: 4.4.1
compile sample:
https://github.com/bytedeco/gradle-javacpp/tree/master/samples/zlib
error info:
root@ubuntu:/home/jni/gradle-javacpp/samples/zlib# gradle wrapper
Starting a Gradle Daemon (subsequent builds will be faster)
FAILURE: Build failed with an exception.
What went wrong:
'org.gradle.api.tasks.TaskProvider org.gradle.api.tasks.TaskContainer.register(java.lang.String, java.lang.Class, org.gradle.api.Action)'
Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Get more help at https://help.gradle.org
BUILD FAILED in 10s
If I try to register BuildTask in build.gradle.kts like that:
tasks.register<BuildTask>("javacppParse$variantName") {
dependsOn(javacppCompileConfig)
setClassPath(arrayOf(javaCompile.destinationDir.toString()))
}
Then I will have this error:
Script compilation error:
Line 103: setClassPath(arrayOf(javaCompile.destinationDir.toString()))
^ Cannot access 'setClassPath': it is package-private in 'BuildTask'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.