pulp-platform / bender Goto Github PK
View Code? Open in Web Editor NEWA dependency management tool for hardware projects.
License: Apache License 2.0
A dependency management tool for hardware projects.
License: Apache License 2.0
I imagine I'm not the only person who would be adding all files in a directory. Having to manually specify the path for each one seems unnecessary, when it could be done with something like:
sources:
- src/*.vhd
- src/**/*.sv
Likely due to #83, the prompt from bender to select a version when there are conflicting requirements may not use the selected version.
My expectation was, that if I create an external import from a repository without specifying any mapping, that it would copy the entire repo structure as is. However, that doesn't seem to be the case. Without adding the dummy entry {from: '', to: ''}
nothing is copied at all. Here is an entry to reproduce the issue:
external_import:
- name: gpio
target_dir: vendored_ips/gpio
upstream: { git: "https://github.com/pulp-platform/gpio.git", rev: "add6f9f8218411a5dc6df524383e2d81695452d1"} #v0.1.1
To avoid doubly listing files, would it be possible to declare defines for all files depending on the target? As an example, this would allow for tracing-specific signals and blocks to be instantiated without using bender's standard TARGET_***
defines. Syntax could be similar to below.
sources:
- defines:
FOO: { target: all(rtl, synth) }
Add a comment to the README indicating that bender will set TARGET_*
defines in the source code. Also add a list of what exact targets are specified for which tools:
https://github.com/fabianschuiki/bender/blob/7fd3d087246ffc9f455e1ef0184baab3d0351147/src/cmd/script.rs#L135-L152
When I run 'bender script verilator' twice on my source tree, I get slightly different results. The files are reordered:
First time:
...
+define+TARGET_SYNTHESIS
+define+TARGET_VERILATOR
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
prim_util_get_scramble_params_0/rtl
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
ibex_ibex_core_0.1/rtl
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/vendor/lowrisc_ip/ip/prim/rtl
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/vendor/lowrisc_ip/dv/sv/dv_utils
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
prim_util_memload_0/rtl
...
Second time:
+define+TARGET_SYNTHESIS
+define+TARGET_VERILATOR
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/vendor/lowrisc_ip/dv/sv/dv_utils
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
dv_dv_fcov_macros_0
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
prim_util_get_scramble_params_0/rtl
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
prim_util_memload_0/rtl
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
ibex_ibex_core_0.1/rtl
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/build/lowrisc_ibex_top_artya7_0.1/src/lowrisc_
prim_assert_0.1/rtl
+incdir+/home/epsilon/work/boxlambda/gw/components/ibex/../../../sub/ibex/vendor/lowrisc_ip/ip/prim/rtl
...
Any idea why this happens and if there's anything I can do to prevent it?
These are the relevant bender.yml manifests:
https://github.com/epsilon537/boxlambda/blob/develop/gw/projects/hello_world/Bender.yml
https://github.com/epsilon537/boxlambda/blob/develop/gw/components/ibex_wb_core/Bender.yml
https://github.com/epsilon537/boxlambda/blob/develop/gw/components/ibex/Bender.yml
I'm using bender 0.27.1
Thanks for any help.
Please add some examples to the readme or into a separate directory outlining the syntax and keywords to describe versions, revisions, targets etc. used in the various configuration files of bender.
When using version override in a Bender.local file, Bender behaves inconsistent to a normal version declaration:
Let's assume the following Bender.yml file of a sub-dependency:
...
dependencies:
foo: {git: "https://github.com/foo/foo.git", version: 0.3.0} # version 0.3.0 = commit-id "abcd"
and the following override file:
overrides:
foo: {git: "https://github.com/foo/foo.git", rev: "1234"}
If we call bender update
followed by bender path foo
we get the following:
/......../.bender/git/checkouts/foo-abcd
Inspecting this directory reveals, that bender checked out commit 1234
within the foo-abcd
directory. First of all, this is unintuitive because the user would expect bender to generate a new version directory like it does for any other (not overriden) dependency.
The second problem is: If commit 1234
does not exist, bender update will not error out but will just keep using commit version abcd
without notifying the user about the non existent override version 1234
.
Expected behavior: Bender should create new directories for override versions and show an error message if it cannot find the commit referenced in an override.
Just now seeing this in the readme.
# Format is the same as `dependencies` in a package manifest.
# DEPRECATED: This will be removed at some point.
plugins:
additional-tools: { path: "/usr/local/additional-tools" }
Wondering if this is true and what the reasoning behind this is? I have found this feature quite useful. I have made packages which act as a means to run tooling via bender. For example, all of my components require a unit testing dependency that allows me to simply kick off a unit test, for any of my components, with something along the lines of bender rtl_sim <args>
. Anyway, I have found the feature quite useful and would be sad to see it go :(.
The diff produced by bender vendor diff
does not include untracked files in the vendor target_dir
.
I guess this is just a missing feature (perhaps in the vendor
tool itself?), but potentially leads to unintended behaviour in our Github action.
following is my vendor_package
settings:
vendor_package:
- name: bextdep
target_dir: vendor/bextdep
upstream: { git: "https://github.com/cliffordwolf/bextdep.git", rev: "b96198514856bfaf85db3e7b0cb1d5f7e0c06d68" }
include_from_upstream:
- "bextdep.v"
- "bextdep_pps.v"
bender script vivado-sim -t rtl -t test
includes files from sources
as expected but does not include the bextdep.v
and bextdep_pps.v
Hi!
Since a recent version of Bender, a parasitic false
appears at the beginning of bender.sources
, making them uninterpretable by Morty. I tried at least with the current 0.27.0
version.
The output source manifest is as below, where the first line is not wanted:
false
[
{
"package": "ariane",
"independent": false,
"target": "all(*, all(*))",
...
git clone https://github.com/openhwgroup/cva6.git
bender sources -f -t ariane > my.sources
head my.sources
And Morty (at least 0.8.0
) does not like it:
morty -f my.sources
error parsing json in `my.sources`: invalid type: boolean `false`, expected a sequence at line 1 column 5
There was a similar issue with similar tools (sv2v I think). I'd suggest either or both:
-o target_file
(or another letter) to avoid using stdout as the way of writing to the output file.Thanks!
Flavien
Currently, bender reports an error when it encounters conflicting version requirements on a dependency. A common scenario where this happens is when I set the revision of a dependency to a feature branch to make a feature that is not yet released available early in development.
In this case, I would like to be able to resolve the conflict interactively and store my decision in the Bender.lock
file.
The interaction could be as follows:
Requirement `^1.2.3` conflicts with other requirements on dependency `common_pkg`:
- package `my_pkg` requires `new_feature`
- package `other_pkg` requires `^1.2.3`
To resolve this conflict manually, select a revision for `common_pkg` among:
1) `1.2.3`
2) `new_feature`
Enter a number or hit enter to abort:
If stdin is closed, bender should maintain its current behavior.
bender script vivado
adds the TARGET_SYNTHESIS
regardless of test flags.
I am running bender import to clone a repo that doesn't support bender. Everything looks good. It really seems like cloning it to /tmp and then checking out the correct commit. But I cannot locate the cloned repo afterwards. My Bender.yml
looks like below. Am I missing something?
# Package metadata. Required.
package:
# The name of the package. Required.
name: my_package
# List of imported files from external repositories not supporting bender. Optional
external_import:
# package name
- name: my_external_repo
# target directory
target_dir: external/my_external_repo
# upstream dependency (i.e. git repository similar to dependencies)
upstream: { git: "ssh://[email protected]/fpga/my_external_repo.git", rev: "224ace1221ebe16fec104c58250faa9f4eac84a2" }
FYI, when I add mapping, it just cannot find the files and errors out.
Should use $ROOT instead.
When you have a git repo as a dependency with one Bender Manifest on its top-level (eg for the whole chip) and another one in a sub-directory, eg generated from a tool like Padrick, then the following happens:
bender update
not bender checkout
bender update
actually seems to work finebender checkout
with an already existing Bender.lock
file (as you would do to ensure everyone is using the same dependencies), then the repo will get checked out but the path in the Bender.lock
file is not updated.Name issue with "sub-directory", export_include_dirs not handled. Could relate to name mismatch, see bender update
What happens is that running bender checkout
(can) change the dependencies hash (?) at the end of the directory name inside .bender/git/checkouts
but it does not update the path for the path-dependency while doing so. This breaks the path dependency.
The warning is also rather confusing and might not even show up if the export_include_dirs
feature is not used.
Ideally this would be fixed by changing the behavior of bender checkout
so it either always used the same hashes (?) when called on the same Bender.lock
file (which would mean the path-dependency stays valid) or it should update the path dependency in the Bender.lock
file or resolve the invalidated path in another way (eg by using links in the internal .bender
structure.
If this is not something you want to support, then I would at least add the bender update
warning for this case to bender checkout
as well.
Ubuntu 21.10 was released on October 14. Could you add the Ubuntu 21.10 package to the latest version?
For recursive bumping of dependencies, the parents
command is already really useful. However, a flag I am really missing for this command is the option to print the (semantic) version requirements along with the parents. This would make it much easier to identify parent packages that need version bumping.
Would it be possible to use environment variables instead of relatives paths in Bender.yml for package path dependencies? We're trying to re-use some things between different projects with different layouts, and being able to use environment variables would make this much more flexible.
package:
name: A
dependencies:
B: {path: "$WORKSPACE/B"}
sources:
- files:
- a.txt
bender update
seems to be very slow on CentOS machines (for a benderized PULP cluster). Specifically, it seems to hang for 2-3 minutes without printing anything just after it clones all repos.
Any idea about possible causes / workarounds / solutions? Unfortunately, I could not really dig into the bowels of the issue... but it doesn't look like an expected behavior.
It appears the file lists in the Bender.yml are static. Perhaps some support to call a hook (Python? Shell Script? Command?) that returns a list of source files.
The specific use case is for the Xilinx IP generators where one might invoke Vivado, create a core, then export the list of files.
Perhaps syntax such as:
sources:
- @(<command to execute>)
- $(<command to execute>)
Not being a Rust developer myself, I'm unsure how to add the behavior myself and generate a pull request.
For certain larger projects, it may be beneficial to incorporate tool-specific arguments for a smaller dependency within the Bender.yml file, such that the argument is only applied to the files in that repository and not all files (current example --vlog-arg= during script generation)
When adding a new package to Bender.yml
and a Bender.lock
file has already been generated, Bender fails and exposes a
thread 'main' panicked at 'no entry found for key', src/sess.rs:181:73
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
It can be solved by either removing Bender.lock
or running bender update
. A direct indication for these steps in the above error message would be nice.
To reproduce the error, follow these steps for a minimal example
mkdir bender_test
and navigate to this directory.Bender.yml
in bender_test
package:
name: bender_test
dependencies:
common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.23.0 }
bender script vsim
Bender.yml
, e.g.package:
name: bender_test
dependencies:
axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.29.1 }
common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.23.0 }
bender script vsim
again, this should cause the panick.Bender doesn't
when generating flists
Dear Bender team,
I am really excited by the possibility of a well-built and widely adopted Verilog package manager. So, thank you very much for developing this project!
I was wondering whether it would also be possible to release pre-built binaries for macOS (the platform that I am using).
Best,
Douwe
Due to an update to tokio and futures in #94, the throttling for futures was removed. If this causes instability when running bender, the throttling will have to be refactored as well. Please report any instability you may notice (possibly too many simultaneous git requests).
Relevant code sections:
src/future_throttle.rs
Lines 500 to 519 in f82ef0e
Lines 528 to 545 in f82ef0e
Lines 809 to 834 in f82ef0e
Lines 892 to 961 in f82ef0e
Git submodules allow the use of a relative path (https://git-scm.com/docs/git-submodule) and is encouraged by GitLab (https://docs.gitlab.com/ee/ci/git_submodules.html). It has a big benefit of allowing the authentication method to be inferred.
It would be great if bender worked with those same relative paths. I believe it would need to get the remote of the current package's repository and resolve the path (removing any instances of /../) to get an absolute one, before continuing as normal.
We may have to add a mechanism that prevents this failure case:
Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.
To add a little more context: I have a makefile-based simulation flow to rapidly explore different configurations, and each simulation run is built using a bender vsim
target. As long as I sequentialize the builds, everything works fine, but with parallel builds the git subprocesses clash.
To revive the library discussion started in #55.
For a lot of the VHDL designs I've seen recently, there was heavy usage of different libraries for each of the sub IP designs.
As far as I am aware, the scripts generated by Bender all use the default library work
as the generated scripts do not specify it.
Patching the generated scripts is a solution, but can be a bit of a hassle when writing the Bender.yml description for more complex VHDL sub-design with different used libraries.
I think there is the opportunity here to extend the functionality of the Bender.yml description for filesets by adding the field library
or something similar:
# Grouped source files may have additional include dirs, defines, target and library:
- include_dirs:
- src/include
- src/stuff/include
defines:
# Define without a value.
EXCLUDE_MAGIC: ~
# Define with a value.
PREFIX_NAME: stuff
target: all(asic, synthesis, freepdk45)
library: core_lib
files:
- src/core/pkg.sv
- src/core/alu.sv
- src/core/top.sv
My Rust expertise is not the best though, but I think this could be quite easily added.
The lockfile currently stores absolute paths. To make things like local working copies easier to manage and exchange, Bender should opportunistically make paths relative if they are a subpath of the current package. The rust std::fs
module should provide functions for this already. This can then also allow the bender script
command to emit relative paths where possible.
In large repositories, an error can occur on bender update
:
error: Failed to spawn child process. Too many open files (os error 24)
A workaround to mitigate this issue is to increase the allowable file limit for the system by increasing ulimit -n
, for example to 4096 by running ulimit -n 4096
. While this currently causes the issue to go away, it doesn't seem like the ultimate solution.
When having the dependency:
riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git", version: 0.3 }
Bender complains:
error: Dependency `riscv-dbg` from `https://github.com/pulp-platform/riscv-dbg.git` cannot satisfy requirement `^0.3`
Hello,
Trying to install bender on Ubuntu 18.04, either from the Rust repos or from source, fails with the following error. Is Ubuntu 18.04 supported? (and Vivado 2018.1 ?)
Thanks in advance.
Best regards,
....
...
Compiling serde_derive v1.0.97
Compiling tokio-signal v0.1.5
Compiling tokio-process v0.1.6
Compiling bender v0.13.1 (/home/aitsaidn/PhD/playground/axspike/bender/bender-0.13.1)
warning: the item `canonicalize` is imported redundantly
--> src/cli.rs:264:19
|
7 | use std::fs::{canonicalize, metadata};
| ------------ the item `canonicalize` is already imported here
...
264 | use std::fs::{canonicalize, metadata};
| ^^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
warning: the item `metadata` is imported redundantly
--> src/cli.rs:264:33
|
7 | use std::fs::{canonicalize, metadata};
| -------- the item `metadata` is already imported here
...
264 | use std::fs::{canonicalize, metadata};
| ^^^^^^^^
warning: the item `fmt` is imported redundantly
--> src/config.rs:493:13
|
13 | use std::fmt;
| -------- the item `fmt` is already imported here
...
493 | use std::fmt;
| ^^^^^^^^
warning: the item `Ordering` is imported redundantly
--> src/sess.rs:1316:13
|
28 | use error::*;
| -------- the item `Ordering` is already imported here
...
1316 | use std::sync::atomic::Ordering;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: the item `Ordering` is imported redundantly
--> src/sess.rs:1323:13
|
28 | use error::*;
| -------- the item `Ordering` is already imported here
...
1323 | use std::sync::atomic::Ordering;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0283]: type annotations required: cannot resolve `std::string::String: std::convert::AsRef<_>`
--> src/sess.rs:338:42
|
338 | self.intern_string(k.as_ref()),
| ^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0283`.
error: failed to compile `bender v0.13.1 (/home/aitsaidn/PhD/playground/axspike/bender/bender-0.13.1)`, intermediate artifacts can be found at `/home/aitsaidn/PhD/playground/axspike/bender/bender-0.13.1/target`
Caused by:
Could not compile `bender`.
To learn more, run the command again with --verbose.
When indicating a checkout_dir
in the top level manifest, bender will correctly clone all dependencies into this directory. If these directories already exist, they are not touched. This is all expected behavior.
Unfortunately, when the manifest in one of these dependencies is changed (to remove a dependency or add a new one), this is not handled by the resolver in bender. The bender resolver (when running bender update
) will use the manifest in the upstream git repository. If the packages are changed this behavior may no longer be consistent, and causes issues such as those described in #72.
A proposed solution is to add an override for all dependencies in case checkout_dir
is set and the path exists, to force a path dependency. The resolver should then use the visible manifests for dependency resolution.
This todo here should be removed (it's okay the way it's implemented right now):
https://github.com/fabianschuiki/bender/blob/5380e96a9c0491bf5975a88f7ebcba550b51524c/src/sess.rs#L942-L943
And the corresponding comment in the README should be adapted.
See https://github.com/japaric/trust for details
Bender ignores version tags in Bender.yml. For instance, the following
dependencies:
common_cells: { git: https://github.com/pulp-platform/common_cells, version: 1.28.0 }
does not use release 1.28.0, instead it uses the latest release.
Version 0.27.1 does not seem to support specifying upstream
dependency revisions using the version
attribute.
With the following Bender.yml
contents:
vendor_package:
- name: musl
target_dir: sw/math
upstream: { git: https://github.com/kraj/musl.git, version: 1.2.4 }
include_from_upstream:
- "src/math/tanh.c"
the bender vendor init
command fails.
It succeeds when specifying the commit hash using the revision
attribute:
vendor_package:
- name: musl
target_dir: sw/math
upstream: { git: https://github.com/kraj/musl.git, rev: 7a43f6fea9081bdd53d8a11cef9e9fab0348c53d }
include_from_upstream:
- "src/math/tanh.c"
I found this comment to be a bit misleading:
Line 185 in dc733b2
Using bender with larger SoC projects that contain many dependencies, we easily run into the issue, that there are semantic versioning conflicts that cannot easily be resolved in the short term (i.e. because the repo that requires version bumping is archived). Requiring to interactively point bender update to the right version to use every time we invoke bender update
or to manually edit the overrides for all of these cases in the Bender.local file can become very cumbersome for larger projects. Since we already have the possibility to override the specific version to use in the Bender.local file I would suggest enhancing the update command to optionally remember the interactive conflict resolution decision of the user by appending the chosen version to the bender.local file. I think an optional flag to the update command that saves each decision to the bender.local file or a yes/no question after every decision would improve user experience.
Description:
I've observed that when using Bender with dependencies pinned to a specific branch, the tool may not update those dependencies if they've already been cloned, even if new commits are pushed to that branch.
To Reproduce:
Set up a my_package
with the following dependencies:
package:
name: my_package
dependencies:
my_common: { git: "/my.git.repo/common.git", rev: my_branch }
Run any Bender command within the my_package
repo for the first time. This causes Bender to clone my_common
at the HEAD of my_branch
.
Push a new commit to my_branch
.
Inside the my_package
repo, run bender update -f
.
Expected Behavior:
The my_common
dependency should be updated to the latest commit on my_branch.
Actual Behavior:
The my_common
dependency is not updated. Upon running bender update -f --debug
, it appears that already-cloned dependencies are treated as Path dependencies, not Git dependencies. This seems to prevent them from being updated.
Questions:
Hi there,
while implementing siphash for my master thesis, I discovered the PULP platform. I'd like to create a bender
package from it to allow other users to use my code.
Since there is no documentation on how to create a package, I'd want to kindly ask you on some help how to create one from my code?
https://github.com/hydroid7/siphash
Thank you in advance.
Best Regards
I'm building off this script for purposes which do not relate to Bender:
bender/.github/workflows/release.yaml
Lines 64 to 65 in 3b489ec
export
at the beginning of line 64 makes the package.sh
script crash with the following error:
tar: target/almalinux8.7/release: Cannot open: No such file or directory
Indeed, it doesn't seem to me that the target/almalinux8.7/release
folder is created anywhere. To my understanding, the reason this bug is not caught is the following:
export
statement, $tgtname
tests empty in package.sh
: bender/.github/scripts/package.sh
Lines 9 to 12 in 3b489ec
target/release
is created as an artifact of this command which is run previously (see difference between --volume
and --mount
options): bender/.github/workflows/release.yaml
Lines 55 to 60 in 3b489ec
To correct this I propose to:
export
statement in line 64 of release.yaml
--volume
option if not necessary (I believe so) and explicitly create the directory on the host: mkdir target/$tgtname/release
package.sh
Trying out the new bender clone
command I noticed that while bender clone name successfully checks out the package and registers it in the Bender.local file it does not update the path corresponding to the just cloned package. This can be forced with a bender update
but intuitively I would have expected that:
bender clone my_package
immediately followed by
bender path my_package
would yield working_dir/my_package
. However, right now the path command still returns the hidden internal git directory until I manually call bender update
...
Hello,
Have you published any article or paper on bender that you would like others to cite?
Suppose we have the following bender vendor package configuration:
# Bender.yml
vendor_package:
- name: musl
target_dir: sw/math
upstream: { git: https://github.com/kraj/musl.git, rev: 7a43f6fea9081bdd53d8a11cef9e9fab0348c53d } # v1.2.4
include_from_upstream:
- "arch/riscv32/bits/alltypes.h.in"
Since the file listed under include_from_upstream
does not exist upstream, the bender vendor init
command will not copy anything, but it still succeeds and explicitly logs:
Copying musl files from upstream
It would be great if it could issue a warning for files not found, e.g.:
arch/riscv32/bits/alltypes.h.in
not found upstream
Bender currently uses old versions of tokio
and futures
:
Lines 17 to 21 in 2a42737
The tokio-core
dependencies have since been deprecated and replaced with tokio
, while futures
has been updated to v0.3. To incorporate bugfixes and improvements in these packages, bender should update to use these newer versions, however there are significant changes to the API which will likely require significant changes within bender.
I have a package that just contains include files (global files that define parts of a larger project). If I attempt to create a Bender file for this, for example:
package:
name: my_package
authors:
- "My Name"
sources:
include_dirs:
- rtl
files:
This doesn't generate any +incdir+ command-line options.
If I add a single dummy file to this, then it adds the required +incdir+ command-line options as well as the dummy file:
package:
name: my_package
authors:
- "My Name"
sources:
include_dirs:
- rtl
files:
- rtl/empty_dummy_module.sv
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.