From 2aaf7808efe44ecfaadd51ae4f8892e667108578 Mon Sep 17 00:00:00 2001 From: login Date: Fri, 11 Nov 2022 22:21:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8=E5=86=85=E6=A0=B8=E4=B8=AD=E5=BC=95?= =?UTF-8?q?=E5=85=A5cbindgen=EF=BC=8C=E7=94=9F=E6=88=90rust-C=E7=9A=84FFI?= =?UTF-8?q?=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 解决codeql失败问题 * new: 为内核引入cbindgen --- .github/workflows/codeql.yml | 70 ---- kernel/.gitignore | 8 +- kernel/Cargo.toml | 4 + kernel/build.rs | 18 +- kernel/cbindgen.toml | 626 +++++++++++++++++++++++++++++++++++ kernel/src/main.c | 3 +- 6 files changed, 651 insertions(+), 78 deletions(-) delete mode 100644 .github/workflows/codeql.yml create mode 100644 kernel/cbindgen.toml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 2e18f25a..00000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,70 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ master ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '23 4 * * 6' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'c' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://git.io/codeql-language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/kernel/.gitignore b/kernel/.gitignore index 31002ed7..da6eb9f5 100644 --- a/kernel/.gitignore +++ b/kernel/.gitignore @@ -1,5 +1,9 @@ target/ src/kernel Cargo.lock -# 将自动生成的Rust FFI加到gitignore -src/include/bindings/bindings.rs \ No newline at end of file + +# 将自动生成的C-Rust FFI加到gitignore +src/include/bindings/bindings.rs +# 将自动生成的Rust-C FFI加到gitignore +src/include/bindings/bindings.h + diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index e3c8925e..bb0ae067 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -8,8 +8,12 @@ edition = "2021" [lib] crate-type = ["staticlib"] +# 运行时依赖项 [dependencies] x86_64 = "0.14.10" +# 构建时依赖项 [build-dependencies] bindgen = "0.61.0" +cbindgen = "0.24.3" + diff --git a/kernel/build.rs b/kernel/build.rs index 90d8d34e..d78d9d02 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -1,12 +1,19 @@ extern crate bindgen; +extern crate cbindgen; + +use ::std::env; + use std::path::PathBuf; fn main() { // Tell cargo to look for shared libraries in the specified directory println!("cargo:rustc-link-search=src"); println!("cargo:rerun-if-changed=src/include/bindings/wrapper.h"); - let binding_file_path = "src/include/bindings/bindings.rs"; + + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let out_path = PathBuf::from(String::from("src/include/bindings/")); + // The bindgen::Builder is the main entry point // to bindgen, and lets you build up options for // the resulting bindings. @@ -30,11 +37,12 @@ fn main() { // Unwrap the Result and panic on failure. .expect("Unable to generate bindings"); - // Write the bindings to the $OUT_DIR/bindings.rs file. - let out_path = PathBuf::from(String::from(".")); - bindings - .write_to_file(out_path.join(binding_file_path)) + .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); } + + cbindgen::generate(crate_dir) + .unwrap() + .write_to_file(out_path.join("bindings.h")); } diff --git a/kernel/cbindgen.toml b/kernel/cbindgen.toml new file mode 100644 index 00000000..19696ac4 --- /dev/null +++ b/kernel/cbindgen.toml @@ -0,0 +1,626 @@ +# The language to output bindings in +# +# possible values: "C", "C++", "Cython" +# +# default: "C++" +language = "C" + + + + +# Options for wrapping the contents of the header: + +# 在文件头部添加的注释信息 +# An optional string of text to output at the beginning of the generated file +# default: doesn't emit anything +header = "/* DragonOS's C FFI for rust. This file is licensed under GPLv2 */" + +# 在文件尾部添加的信息 +# An optional string of text to output at the end of the generated file +# default: doesn't emit anything +# trailer = "/* Text to put at the end of the generated file */" + +# An optional name to use as an include guard +# default: doesn't emit an include guard +# include_guard = "mozilla_wr_bindings_h" + +# 是否生成一个 `#pragma once` +pragma_once = true + +# An optional string of text to output between major sections of the generated +# file as a warning against manual editing +# +# default: doesn't emit anything +autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" + +# Whether to include a comment with the version of cbindgen used to generate the file +# default: false +# include_version = true + +# An optional namespace to output around the generated bindings +# default: doesn't emit a namespace +namespace = "ffi" + +# An optional list of namespaces to output around the generated bindings +# default: [] +# namespaces = ["mozilla", "wr"] + +# An optional list of namespaces to declare as using with "using namespace" +# default: [] +# using_namespaces = ["mozilla", "wr"] + +# A list of sys headers to #include (with angle brackets) +# default: [] +sys_includes = [] + +# 生成的binding文件要include的头文件 +# A list of headers to #include (with quotes) +# default: [] +includes = ["stdint.h"] + +# Whether cbindgen's default C/C++ standard imports should be suppressed. These +# imports are included by default because our generated headers tend to require +# them (e.g. for uint32_t). Currently, the generated imports are: +# +# * for C: , , , , +# +# * for C++: , , , , (depending on config) +# +# default: false +no_includes = true + +# Whether to make a C header C++ compatible. +# These will wrap generated functions into a `extern "C"` block, e.g. +# +# #ifdef __cplusplus +# extern "C" { +# #endif // __cplusplus +# +# // Generated functions. +# +# #ifdef __cplusplus +# } // extern "C" +# #endif // __cplusplus +# +# If the language is not C this option won't have any effect. +# +# default: false +cpp_compat = false + +# A list of lines to add verbatim after the includes block +#after_includes = "#define VERSION 1" + + + +# Code Style Options + +# The style to use for curly braces +# +# possible values: "SameLine", "NextLine" +# +# default: "SameLine" +braces = "NextLine" + +# The desired length of a line to use when formatting lines +# default: 100 +line_length = 120 + +# The amount of spaces to indent by +# default: 2 +tab_width = 4 + +# Include doc comments from Rust as documentation +documentation = true + +# How the generated documentation should be commented. +# +# possible values: +# * "c": /* like this */ +# * "c99": // like this +# * "c++": /// like this +# * "doxy": like C, but with leading *'s on each line +# * "auto": "c++" if that's the language, "doxy" otherwise +# +# default: "auto" +documentation_style = "doxy" + +# How much of the documentation for each item is output. +# +# possible values: +# * "short": Only the first line. +# * "full": The full documentation. +# +# default: "full" +documentation_length = "short" + + + + +# Codegen Options + +# When generating a C header, the kind of declaration style to use for structs +# or enums. +# +# possible values: +# * "type": typedef struct { ... } MyType; +# * "tag": struct MyType { ... }; +# * "both": typedef struct MyType { ... } MyType; +# +# default: "both" +style = "both" + +# If this option is true `usize` and `isize` will be converted into `size_t` and `ptrdiff_t` +# instead of `uintptr_t` and `intptr_t` respectively. +usize_is_size_t = true + +# A list of substitutions for converting cfg's to ifdefs. cfgs which aren't +# defined here will just be discarded. +# +# e.g. +# `#[cfg(target = "freebsd")] ...` +# becomes +# `#if defined(DEFINE_FREEBSD) ... #endif` +[defines] +"target_os = freebsd" = "DEFINE_FREEBSD" +"feature = serde" = "DEFINE_SERDE" + + + + + +[export] +# A list of additional items to always include in the generated bindings if they're +# found but otherwise don't appear to be used by the public API. +# +# default: [] +include = ["MyOrphanStruct", "MyGreatTypeRename"] + +# A list of items to not include in the generated bindings +# default: [] +exclude = ["Bad"] + +# 生成的内容的前缀 +# A prefix to add before the name of every item +# default: no prefix is added +# prefix = "CAPI_" + +# Types of items that we'll generate. If empty, then all types of item are emitted. +# +# possible items: (TODO: explain these in detail) +# * "constants": +# * "globals": +# * "enums": +# * "structs": +# * "unions": +# * "typedefs": +# * "opaque": +# * "functions": +# +# default: [] +item_types = ["enums", "structs", "opaque", "functions"] + +# Whether applying rules in export.rename prevents export.prefix from applying. +# +# e.g. given this toml: +# +# [export] +# prefix = "capi_" +# [export.rename] +# "MyType" = "my_cool_type" +# +# You get the following results: +# +# renaming_overrides_prefixing = true: +# "MyType" => "my_cool_type" +# +# renaming_overrides_prefixing = false: +# "MyType => capi_my_cool_type" +# +# default: false +renaming_overrides_prefixing = true + +# Table of name conversions to apply to item names (lhs becomes rhs) +[export.rename] +"MyType" = "my_cool_type" +"my_function" = "BetterFunctionName" + +# Table of things to prepend to the body of any struct, union, or enum that has the +# given name. This can be used to add things like methods which don't change ABI, +# mark fields private, etc +[export.pre_body] +"MyType" = """ + MyType() = delete; +private: +""" + +# Table of things to append to the body of any struct, union, or enum that has the +# given name. This can be used to add things like methods which don't change ABI. +[export.body] +"MyType" = """ + void cppMethod() const; +""" + +# Configuration for name mangling +[export.mangle] +# Whether the types should be renamed during mangling, for example +# c_char -> CChar, etc. +rename_types = "PascalCase" +# Whether the underscores from the mangled name should be omitted. +remove_underscores = false + +[layout] +# A string that should come before the name of any type which has been marked +# as `#[repr(packed)]`. For instance, "__attribute__((packed))" would be a +# reasonable value if targeting gcc/clang. A more portable solution would +# involve emitting the name of a macro which you define in a platform-specific +# way. e.g. "PACKED" +# +# default: `#[repr(packed)]` types will be treated as opaque, since it would +# be unsafe for C callers to use a incorrectly laid-out union. +packed = "PACKED" + +# A string that should come before the name of any type which has been marked +# as `#[repr(align(n))]`. This string must be a function-like macro which takes +# a single argument (the requested alignment, `n`). For instance, a macro +# `#define`d as `ALIGNED(n)` in `header` which translates to +# `__attribute__((aligned(n)))` would be a reasonable value if targeting +# gcc/clang. +# +# default: `#[repr(align(n))]` types will be treated as opaque, since it +# could be unsafe for C callers to use a incorrectly-aligned union. +aligned_n = "ALIGNED" + + +[fn] +# 函数开头要加入的内容 +# An optional prefix to put before every function declaration +# default: no prefix added +# prefix = "WR_START_FUNC" + +# 函数声明的结尾要加入的内容 +# An optional postfix to put after any function declaration +# default: no postix added +# postfix = "WR_END_FUNC" + +# How to format function arguments +# +# possible values: +# * "horizontal": place all arguments on the same line +# * "vertical": place each argument on its own line +# * "auto": only use vertical if horizontal would exceed line_length +# +# default: "auto" +args = "horizontal" + +# An optional string that should prefix function declarations which have been +# marked as `#[must_use]`. For instance, "__attribute__((warn_unused_result))" +# would be a reasonable value if targeting gcc/clang. A more portable solution +# would involve emitting the name of a macro which you define in a +# platform-specific way. e.g. "MUST_USE_FUNC" +# default: nothing is emitted for must_use functions +must_use = "MUST_USE_FUNC" + +# An optional string that will be used in the attribute position for functions +# that don't return (that return `!` in Rust). +# +# For instance, `__attribute__((noreturn))` would be a reasonable value if +# targeting gcc/clang. +no_return = "NO_RETURN" + +# An optional string that, if present, will be used to generate Swift function +# and method signatures for generated functions, for example "CF_SWIFT_NAME". +# If no such macro is available in your toolchain, you can define one using the +# `header` option in cbindgen.toml +# default: no swift_name function attributes are generated +# swift_name_macro = "CF_SWIFT_NAME" + +# A rule to use to rename function argument names. The renaming assumes the input +# is the Rust standard snake_case, however it accepts all the different rename_args +# inputs. This means many options here are no-ops or redundant. +# +# possible values (that actually do something): +# * "CamelCase": my_arg => myArg +# * "PascalCase": my_arg => MyArg +# * "GeckoCase": my_arg => aMyArg +# * "ScreamingSnakeCase": my_arg => MY_ARG +# * "None": apply no renaming +# +# technically possible values (that shouldn't have a purpose here): +# * "SnakeCase": apply no renaming +# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?) +# * "UpperCase": same as ScreamingSnakeCase in this context +# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context +# +# default: "None" +rename_args = "PascalCase" + +# This rule specifies the order in which functions will be sorted. +# +# "Name": sort by the name of the function +# "None": keep order in which the functions have been parsed +# +# default: "None" +sort_by = "Name" + +[struct] +# A rule to use to rename struct field names. The renaming assumes the input is +# the Rust standard snake_case, however it acccepts all the different rename_args +# inputs. This means many options here are no-ops or redundant. +# +# possible values (that actually do something): +# * "CamelCase": my_arg => myArg +# * "PascalCase": my_arg => MyArg +# * "GeckoCase": my_arg => mMyArg +# * "ScreamingSnakeCase": my_arg => MY_ARG +# * "None": apply no renaming +# +# technically possible values (that shouldn't have a purpose here): +# * "SnakeCase": apply no renaming +# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?) +# * "UpperCase": same as ScreamingSnakeCase in this context +# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context +# +# default: "None" +rename_fields = "PascalCase" + +# An optional string that should come before the name of any struct which has been +# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))" +# would be a reasonable value if targeting gcc/clang. A more portable solution +# would involve emitting the name of a macro which you define in a +# platform-specific way. e.g. "MUST_USE_STRUCT" +# +# default: nothing is emitted for must_use structs +must_use = "MUST_USE_STRUCT" + +# Whether a Rust type with associated consts should emit those consts inside the +# type's body. Otherwise they will be emitted trailing and with the type's name +# prefixed. This does nothing if the target is C, or if +# [const]allow_static_const = false +# +# default: false +# associated_constants_in_body: false + +# Whether to derive a simple constructor that takes a value for every field. +# default: false +derive_constructor = true + +# Whether to derive an operator== for all structs +# default: false +derive_eq = false + +# Whether to derive an operator!= for all structs +# default: false +derive_neq = false + +# Whether to derive an operator< for all structs +# default: false +derive_lt = false + +# Whether to derive an operator<= for all structs +# default: false +derive_lte = false + +# Whether to derive an operator> for all structs +# default: false +derive_gt = false + +# Whether to derive an operator>= for all structs +# default: false +derive_gte = false + + + + + +[enum] +# A rule to use to rename enum variants, and the names of any fields those +# variants have. This should probably be split up into two separate options, but +# for now, they're the same! See the documentation for `[struct]rename_fields` +# for how this applies to fields. Renaming of the variant assumes that the input +# is the Rust standard PascalCase. In the case of QualifiedScreamingSnakeCase, +# it also assumed that the enum's name is PascalCase. +# +# possible values (that actually do something): +# * "CamelCase": MyVariant => myVariant +# * "SnakeCase": MyVariant => my_variant +# * "ScreamingSnakeCase": MyVariant => MY_VARIANT +# * "QualifiedScreamingSnakeCase": MyVariant => ENUM_NAME_MY_VARIANT +# * "LowerCase": MyVariant => myvariant +# * "UpperCase": MyVariant => MYVARIANT +# * "None": apply no renaming +# +# technically possible values (that shouldn't have a purpose for the variants): +# * "PascalCase": apply no renaming +# * "GeckoCase": apply no renaming +# +# default: "None" +rename_variants = "None" + +# Whether an extra "sentinel" enum variant should be added to all generated enums. +# Firefox uses this for their IPC serialization library. +# +# WARNING: if the sentinel is ever passed into Rust, behaviour will be Undefined. +# Rust does not know about this value, and will assume it cannot happen. +# +# default: false +add_sentinel = false + +# Whether enum variant names should be prefixed with the name of the enum. +# default: false +prefix_with_name = false + +# Whether to emit enums using "enum class" when targeting C++. +# default: true +enum_class = true + +# Whether to generate static `::MyVariant(..)` constructors and `bool IsMyVariant()` +# methods for enums with fields. +# +# default: false +derive_helper_methods = false + +# Whether to generate `const MyVariant& AsMyVariant() const` methods for enums with fields. +# default: false +derive_const_casts = false + +# Whether to generate `MyVariant& AsMyVariant()` methods for enums with fields +# default: false +derive_mut_casts = false + +# The name of the macro/function to use for asserting `IsMyVariant()` in the body of +# derived `AsMyVariant()` cast methods. +# +# default: "assert" (but also causes `` to be included by default) +cast_assert_name = "MOZ_RELEASE_ASSERT" + +# An optional string that should come before the name of any enum which has been +# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))" +# would be a reasonable value if targeting gcc/clang. A more portable solution +# would involve emitting the name of a macro which you define in a +# platform-specific way. e.g. "MUST_USE_ENUM" +# +# Note that this refers to the *output* type. That means this will not apply to an enum +# with fields, as it will be emitted as a struct. `[struct]must_use` will apply there. +# +# default: nothing is emitted for must_use enums +must_use = "MUST_USE_ENUM" + +# Whether enums with fields should generate destructors. This exists so that generic +# enums can be properly instantiated with payloads that are C++ types with +# destructors. This isn't necessary for structs because C++ has rules to +# automatically derive the correct constructors and destructors for those types. +# +# Care should be taken with this option, as Rust and C++ cannot +# properly interoperate with eachother's notions of destructors. Also, this may +# change the ABI for the type. Either your destructor-full enums must live +# exclusively within C++, or they must only be passed by-reference between +# C++ and Rust. +# +# default: false +derive_tagged_enum_destructor = false + +# Whether enums with fields should generate copy-constructor. See the discussion on +# derive_tagged_enum_destructor for why this is both useful and very dangerous. +# +# default: false +derive_tagged_enum_copy_constructor = false +# Whether enums with fields should generate copy-assignment operators. +# +# This depends on also deriving copy-constructors, and it is highly encouraged +# for this to be set to true. +# +# default: false +derive_tagged_enum_copy_assignment = false + +# Whether enums with fields should generate an empty, private destructor. +# This allows the auto-generated constructor functions to compile, if there are +# non-trivially constructible members. This falls in the same family of +# dangerousness as `derive_tagged_enum_copy_constructor` and co. +# +# default: false +private_default_tagged_enum_constructor = false + + + + + +[const] +# Whether a generated constant can be a static const in C++ mode. I have no +# idea why you would turn this off. +# +# default: true +allow_static_const = true + +# Whether a generated constant can be constexpr in C++ mode. +# +# default: true +allow_constexpr = false + +# This rule specifies the order in which constants will be sorted. +# +# "Name": sort by the name of the constant +# "None": keep order in which the constants have been parsed +# +# default: "None" +sort_by = "Name" + + + + +[macro_expansion] +# Whether bindings should be generated for instances of the bitflags! macro. +# default: false +bitflags = true + + + + + + +# Options for how your Rust library should be parsed + +[parse] +# Whether to parse dependent crates and include their types in the output +# default: false +parse_deps = true + +# A white list of crate names that are allowed to be parsed. If this is defined, +# only crates found in this list will ever be parsed. +# +# default: there is no whitelist (NOTE: this is the opposite of []) +include = ["webrender", "webrender_traits"] + +# A black list of crate names that are not allowed to be parsed. +# default: [] +exclude = ["libc"] + +# Whether to use a new temporary target directory when running `rustc -Zunpretty=expanded`. +# This may be required for some build processes. +# +# default: false +clean = false + +# Which crates other than the top-level binding crate we should generate +# bindings for. +# +# default: [] +extra_bindings = ["my_awesome_dep"] + +[parse.expand] +# A list of crate names that should be run through `cargo expand` before +# parsing to expand any macros. Note that if a crate is named here, it +# will always be parsed, even if the blacklist/whitelist says it shouldn't be. +# +# default: [] +crates = ["euclid"] + +# If enabled, use the `--all-features` option when expanding. Ignored when +# `features` is set. For backwards-compatibility, this is forced on if +# `expand = ["euclid"]` shorthand is used. +# +# default: false +all_features = false + +# When `all_features` is disabled and this is also disabled, use the +# `--no-default-features` option when expanding. +# +# default: true +default_features = true + +# A list of feature names that should be used when running `cargo expand`. This +# combines with `default_features` like in your `Cargo.toml`. Note that the features +# listed here are features for the current crate being built, *not* the crates +# being expanded. The crate's `Cargo.toml` must take care of enabling the +# appropriate features in its dependencies +# +# default: [] +features = ["cbindgen"] + +[ptr] +# An optional string to decorate all pointers that are +# required to be non null. Nullability is inferred from the Rust type: `&T`, +# `&mut T` and `NonNull` all require a valid pointer value. +non_null_attribute = "_Nonnull" + +# Options specific to Cython bindings. + diff --git a/kernel/src/main.c b/kernel/src/main.c index ab25bfae..3684f248 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -41,7 +41,8 @@ #include ul bsp_idt_size, bsp_gdt_size; -extern int __rust_demo_func(); + +#include #pragma GCC push_options #pragma GCC optimize("O0")