#opencl #preprocessor #include #source-file #handle #line-numbers

ocl-include

简单的预处理器,实现了OpenCL源文件的#include机制

10个版本

0.6.0 2023年4月18日
0.5.1 2021年5月28日
0.4.1 2021年4月6日
0.3.4 2021年2月13日
0.2.0 2019年6月14日

#428 in 解析器实现

Download history 2/week @ 2024-03-09 50/week @ 2024-03-30 11/week @ 2024-04-06 2/week @ 2024-05-18

101 每月下载量
用于 4 个Crates(2个直接使用)

MIT/Apache

40KB
1K SLoC

ocl-include

Crates.io Docs.rs Travis CI Appveyor Codecov.io License

简单的预处理器,实现了OpenCL源文件的#include机制。

关于

OpenCL API不提供将头文件包含到主文件中的机制,类似于C和C++。这个包是一个简单的预处理器,处理源文件中的#include ...#pragma once指令,在文件系统或内存中收集它们,并将单个字符串输出,可以传递给OpenCL内核构建器。它还提供了一种机制,可以通过生成的字符串中的行号来查找源文件及其位置,这对于处理OpenCL编译器消息很有帮助。

文档

示例

假设您在./examples/文件夹中有main.cheader.h文件

main.c:

#include <header.h>

int main() {
    return RET_CODE;
}

header.h:

#pragma once

static const int RET_CODE = 0;

仅文件系统

以下代码从文件系统中获取main.c并将其包含到header.h中。

use ocl_include::*;
use std::path::Path;

fn main() {
    let parser = Parser::builder()
        .add_source(
            source::Fs::builder()
                .include_dir(&Path::new("./examples"))
                .unwrap()
                .build(),
        )
        .build();
    let node = parser.parse(Path::new("main.c")).unwrap();

    println!("{}", node.collect().0);
}

文件系统和内存

以下代码从内存中获取main.c源代码,并从文件系统中将其包含到header.h中。

use ocl_include::*;
use std::path::Path;

fn main() {
    let main = r"
    #include <header.h>
    int main() {
        return ~RET_CODE;
    }
    ";

    let parser = Parser::builder()
        .add_source(
            source::Mem::builder()
                .add_file(&Path::new("main.c"), main.to_string())
                .unwrap()
                .build(),
        )
        .add_source(
            source::Fs::builder()
                .include_dir(&Path::new("./examples"))
                .unwrap()
                .build(),
        )
        .build();
    let node = parser.parse(Path::new("main.c")).unwrap();

    println!("{}", node.collect().0);
}

索引

Node.collect()还返回一个Index实例作为秒值。它可以用来通过生成的字符串中的行号查找源文件及其行号。

假设我们的OpenCL编译器接受生成的字符串并在某些行失败。但是行号对我们没有帮助,因为我们不知道这个行号来自哪个源文件。幸运的是,有一个Index::search可以用来查找。

use ocl_include::*;
use std::path::Path;

fn main() {
    let parser = Parser::builder()
        .add_source(
            source::Fs::builder()
                .include_dir(&Path::new("./examples"))
                .unwrap()
                .build(),
        )
        .build();
    let node = parser.parse(Path::new("main.c")).unwrap();
    let (generated, index) = node.collect();

    // Let's imagine that we complie the code here
    // and got a compiler message at specific line
    let line = 4;
    println!(
        "line {}: '{}'",
        line,
        generated.lines().nth(line - 1).unwrap()
    );

    // This will find the origin of this line
    let (path, local_line) = index.search(line - 1).unwrap();

    println!("origin: '{}' at line {}", path, local_line + 1);
}

其他预处理器功能

解析器还支持使用简单的预处理器门过滤代码(#if(n)def#else#endif)。

默认情况下,过滤是禁用的,要为特定定义启用它,请使用 ParserBuilder::add_flag(flag_name, is_defined)

来源

来源是一个通过名称检索文件的处理器。

该仓库目前包含以下来源

  • Fs:从文件系统中获取文件。
  • Mem:从内存中检索来源。

以下组合也是来源

  • Vec<S> where S: Source:尝试从来源中依次检索文件。
  • &S其中S:Source
  • Box<dyn Source>
  • Rc<S> 其中S:Source

许可

根据您的选择,许可为以下之一

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的您有意提交以包含在作品中的任何贡献,将根据上述内容双许可,没有任何附加条款或条件。

依赖关系

~2.1-3MB
~53K SLoC