-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wip] initial rust ffi support (fails to build)
- Loading branch information
Showing
10 changed files
with
271 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[build] | ||
target = "thumbv6m-none-eabi" | ||
|
||
[unstable] | ||
build-std = ["core", "panic_abort"] | ||
build-std-features = ["panic_immediate_abort"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
.pio | ||
/.pio/ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "usb3sun" | ||
edition = "2021" | ||
version = "2.0.0" | ||
readme = "README.md" | ||
|
||
[lib] | ||
path = "src/lib.rs" | ||
name = "usb3sun" | ||
edition = "2021" | ||
crate-type = ["staticlib"] | ||
required-features = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Cargo <-> PlatformIO integration script (autogenerated by cargo-pio) | ||
# Calling 'pio run' will also build the Rust library crate by invoking Cargo | ||
# | ||
# How to use: Insert/update the following line in one of platformio.ini's environments: | ||
# extra_scripts = platformio.cargo.py | ||
|
||
import os | ||
|
||
Import("env") | ||
|
||
class Cargo: | ||
def run(self, env): | ||
self.__init_props(env) | ||
|
||
if self.__cargo_run_before_project: | ||
# Attach as a pre-action to all source files so that in case CBindgen is used | ||
# the C headers are generated before the files are compiled | ||
env.AddPreAction(Glob(os.path.join(env.subst("$BUILD_DIR"), "src/*.o")), self.__run_cargo) | ||
|
||
# Hack. Need to always run when a C file from the src directory is built, or else the include directories | ||
# passed to Cargo will not contain the includes coming from libraries imported with PlatformIO's Library Manager | ||
env.AlwaysBuild(os.path.join(env.subst("$BUILD_DIR"), "src/dummy.o")) | ||
|
||
env.AddPreAction("$BUILD_DIR/$PROGNAME$PROGSUFFIX", [self.__run_cargo, self.__link_cargo]) | ||
|
||
def __init_props(self, env): | ||
self.__cargo_ran = False | ||
|
||
self.__rust_lib = env.GetProjectOption("rust_lib") | ||
self.__rust_target = env.GetProjectOption("rust_target") | ||
|
||
self.__rust_bindgen_enabled = env.GetProjectOption("rust_bindgen_enabled", default = "false").lower() == "true" | ||
self.__rust_bindgen_extra_clang_args = env.GetProjectOption("rust_bindgen_extra_clang_args", default = "") | ||
|
||
self.__cargo_run_before_project = env.GetProjectOption("cargo_run_before_project", default = "false").lower() == "true" | ||
self.__cargo_options = env.GetProjectOption("cargo_options", default = "") | ||
self.__cargo_profile = env.GetProjectOption( | ||
"cargo_profile", | ||
default = "release" if env.GetProjectOption("build_type") == "release" else "debug") | ||
self.__cargo_target_dir = env.GetProjectOption( | ||
"cargo_target_dir", | ||
default = os.path.join(env.subst("$PROJECT_BUILD_DIR"), "cargo") | ||
if env.GetProjectOption("cargo_pio_common_build_dir", default = "").lower() == "true" | ||
else os.path.join(env.subst("$PROJECT_DIR"), "target")) | ||
|
||
def __run_cargo(self, source, target, env): | ||
if self.__cargo_ran: | ||
return 0 | ||
|
||
print(">>> CARGO") | ||
|
||
board_mcu = env.get("BOARD_MCU") | ||
if not board_mcu and "BOARD" in env: | ||
board_mcu = env.BoardConfig().get("build.mcu") | ||
|
||
env["ENV"]["CARGO_BUILD_TARGET_DIR"] = self.__cargo_target_dir | ||
env["ENV"]["CARGO_PIO_BUILD_PROJECT_DIR"] = env.subst("$PROJECT_DIR") | ||
env["ENV"]["CARGO_PIO_BUILD_RELEASE_BUILD"] = str(env.GetProjectOption("build_type", default = "release") == "release") | ||
|
||
env["ENV"]["CARGO_PIO_BUILD_PATH"] = env["ENV"]["PATH"] | ||
env["ENV"]["CARGO_PIO_BUILD_ACTIVE"] = "1" | ||
env["ENV"]["CARGO_PIO_BUILD_INC_FLAGS"] = env.subst("$_CPPINCFLAGS") | ||
env["ENV"]["CARGO_PIO_BUILD_LIB_FLAGS"] = env.subst("$_LIBFLAGS") | ||
env["ENV"]["CARGO_PIO_BUILD_LIB_DIR_FLAGS"] = env.subst("$_LIBDIRFLAGS") | ||
env["ENV"]["CARGO_PIO_BUILD_LIBS"] = env.subst("$LIBS") | ||
env["ENV"]["CARGO_PIO_BUILD_LINK_FLAGS"] = env.subst("$LINKFLAGS") | ||
env["ENV"]["CARGO_PIO_BUILD_LINK"] = env.subst("$LINK") | ||
env["ENV"]["CARGO_PIO_BUILD_LINKCOM"] = env.subst("$LINKCOM") | ||
env["ENV"]["CARGO_PIO_BUILD_MCU"] = board_mcu | ||
|
||
if self.__rust_bindgen_enabled: | ||
env["ENV"]["CARGO_PIO_BUILD_BINDGEN_RUN"] = "True" | ||
env["ENV"]["CARGO_PIO_BUILD_BINDGEN_EXTRA_CLANG_ARGS"] = self.__rust_bindgen_extra_clang_args | ||
|
||
env["ENV"]["CARGO_PIO_BUILD_PIO_PLATFORM_DIR"] = env.PioPlatform().get_dir()[0] | ||
env["ENV"]["CARGO_PIO_BUILD_PIO_FRAMEWORK_DIR"] = env.PioPlatform().get_package_dir(env.PioPlatform().frameworks[env.GetProjectOption("framework")[0]]["package"]) | ||
|
||
self.__cargo_ran = True | ||
result = env.Execute(f"cargo build {'--release' if self.__cargo_profile == 'release' else ''} --lib --target {self.__rust_target} {self.__cargo_options}") | ||
|
||
print("<<< CARGO") | ||
|
||
return result | ||
|
||
def __link_cargo(self, source, target, env): | ||
env.Prepend(LINKFLAGS = ["-Wl,--allow-multiple-definition"]) # A hack to workaround this issue with Rust's compiler intrinsics: https://github.com/rust-lang/compiler-builtins/issues/353 | ||
env.Prepend(LIBPATH = [env.subst(os.path.join(self.__cargo_target_dir, self.__rust_target, self.__cargo_profile))]) | ||
env.Prepend(LIBS = [self.__rust_lib]) | ||
|
||
Cargo().run(env) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# A small PlatformIO integration script (autogenerated by cargo-pio) that provides the capability to clone | ||
# user-specified Git projects (platformio.ini git_repos = "...") before the build is triggered | ||
# | ||
# How to use: | ||
# Insert/update the following line in one of platformio.ini's environments: | ||
# extra_scripts = pre:platformio.git.py | ||
# Specify a newline-separated list of Git repos to check out: | ||
# git_repos = [dir-name1]@<repo1> \n [dir-name2]@<repo2>... | ||
|
||
import os | ||
|
||
Import("env") | ||
|
||
class GitRepos: | ||
def run(self, env): | ||
self.__git_repos = env.GetProjectOption("git_repos", default = "") | ||
self.__materialize_git_repos() | ||
|
||
def __materialize_git_repos(self): | ||
for (directory, repo) in self.__git_repos_list(): | ||
if not os.path.exists(env.subst(directory)): | ||
print(f"Cloning {repo} as directory {directory}") | ||
if env.Execute(f"git clone {repo} {directory}"): | ||
Exit(1) | ||
|
||
def __git_repos_list(self): | ||
git_repos_dir = os.path.join("$PROJECT_WORKSPACE_DIR", "git-repos") | ||
|
||
def get_repo(item): | ||
repo = item | ||
repo_directory = repo.split("/")[-1] | ||
if "@" in item: | ||
repo_directory, repo = item.split("@", 1) | ||
|
||
return ( | ||
os.path.join(git_repos_dir, repo_directory.strip()), | ||
repo.strip()) | ||
|
||
return [get_repo(item) for item in self.__git_repos.split("\n") if len(item.strip()) > 0] | ||
|
||
GitRepos().run(env) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# A small PlatformIO integration script (autogenerated by cargo-pio) that provides the capability to patch | ||
# PlatformIO packages (or the platform itself) before the build is triggered | ||
# | ||
# How to use: | ||
# Insert/update the following line in one of platformio.ini's environments: | ||
# extra_scripts = pre:platformio.patch.py | ||
# Specify a newline-separated list of patches to apply: | ||
# patches = <pio-package-directory1>@<patch-file1> \n <pio-package-directory2>@<patch-file2>... | ||
# ... where <patch-file-1>, <patch-file-2> etc. are expected to be placed in a 'patches/' folder of your project | ||
# | ||
# When <pio-package-directory> is equal to "__platform__", the platform itself will be patched | ||
|
||
import os | ||
import shutil | ||
|
||
Import("env") | ||
|
||
class Patch: | ||
def run(self, env): | ||
for (patch, patch_name, dir) in self.__patches_list(env): | ||
self.__patch(env, patch, patch_name, dir) | ||
|
||
def __patch(self, env, patch, patch_name, dir): | ||
patch_flag = os.path.join(dir, f"{patch_name}.applied") | ||
|
||
if not os.path.isfile(patch_flag): | ||
# In recent PlatformIO, framework_espidf is no longer a true GIT repository | ||
# (i.e. it does not contain a .git subfolder) | ||
# As a result, "git apply" does not really work | ||
# | ||
# One workaround would've been to use `patch` instead of `git apply`, | ||
# however `patch` does not seem to be available on Windows out of the box | ||
# | ||
# Therefore, instead we do a nasty hack here: we check if `dir` | ||
# contains a `.git` folder, and if not we create it using "git init" | ||
# | ||
# Once the patch is applied, we remove the `.git` folder | ||
git_dir = os.path.join(dir, ".git") | ||
git_dir_exists = True | ||
|
||
if not os.path.exists(git_dir): | ||
if env.Execute("git init", chdir = dir): | ||
env.Exit(1) | ||
git_dir_exists = False | ||
|
||
res = env.Execute(f"git apply {patch}", chdir = dir) | ||
|
||
if not git_dir_exists: | ||
shutil.rmtree(git_dir) | ||
|
||
if res: | ||
env.Exit(1) | ||
|
||
self.__touch(patch_flag) | ||
|
||
def __patches_list(self, env): | ||
patches_dir = os.path.join(env.subst("$PROJECT_DIR"), "patches") | ||
|
||
def get_patch(item): | ||
dir, patch = item.split("@", 1) | ||
|
||
package = dir.strip() | ||
if package == "__platform__": | ||
package_dir = env.PioPlatform().get_dir() | ||
else: | ||
package_dir = env.PioPlatform().get_package_dir(package) | ||
|
||
return ( | ||
os.path.join(patches_dir, patch.strip()), | ||
patch.strip(), | ||
package_dir) | ||
|
||
return [get_patch(item) for item in env.GetProjectOption("patches", default = "").split("\n") if len(item.strip()) > 0] | ||
|
||
def __touch(self, path): | ||
os.open(path, os.O_CREAT | os.O_RDWR) | ||
|
||
Patch().run(env) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// | ||
// Cargo <-> PlatformIO helper C file (autogenerated by cargo-pio) | ||
// This file is intentionally empty. Please DO NOT change it or delete it! | ||
// | ||
// Two reasons why this file is necessary: | ||
// - PlatformIO complains if the src directory is empty with an error message | ||
// 'Nothing to build. Please put your source code files to '../src' folder'. So we have to provide at least one C/C++ source file | ||
// - The Cargo invocation is attached as a post-action to building this file. This is necessary, or else | ||
// Cargo crates will not see the extra include directories of all libraries downloaded via the PlatformIO Library Manager | ||
// |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Remove if STD is supported for your platform and you plan to use it | ||
#![no_std] | ||
|
||
// Remove if STD is supported for your platform and you plan to use it | ||
#[panic_handler] | ||
fn panic(_info: &core::panic::PanicInfo) -> ! { | ||
loop {} | ||
} | ||
|
||
// | ||
// Entry points | ||
// | ||
|
||
#[no_mangle] | ||
extern "C" fn arduino_setup() { | ||
} | ||
|
||
#[no_mangle] | ||
extern "C" fn arduino_loop() { | ||
} |