diff --git a/.gitignore b/.gitignore index abc98742c..04dcdd2f8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ rusty-tags.vi run notes bench.csv +*.dylib +*.so +*.dll diff --git a/Cargo.toml b/Cargo.toml index 80ac68c39..866763f0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,7 @@ [package] name = "weld" version = "0.1.0" -authors = ["Matei Zaharia ", - "Shoumik Palkar ", - "Deepak Narayanan ", - "James Thomas "] +authors = ["Weld Developers "] build = "build.rs" [dependencies] diff --git a/README.md b/README.md index 67e2c4a6f..043a47852 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,27 @@ # Weld +Weld is a language and runtime for improving the performance of data-intensive applications. It optimizes across libraries and functions by expressing the core computations in libraries using a common intermediate representation, and optimizing across each framework. + +Modern analytics applications combine multiple functions from different libraries and frameworks to build complex workflows. Even though individual functions can achieve high performance in isolation, the performance of the combined workflow is often an order of magnitude below hardware limits due to extensive data movement across the functions. Weld’s take on solving this problem is to lazily build up a computation for the entire workflow, and then optimizing and evaluating it only when a result is needed. + +## Contents + + * [Building](#building) + - [MacOS LLVM Installation](#macos-llvm-installation) + - [Ubuntu LLVM Installation](#ubuntu-llvm-installation) + - [Building Weld](#building-weld) + * [Documentation](#documentation) + * [Grizzly](#grizzly) + * [Running an Interactive REPL](#running-an-interactive-repl) + * [Benchmarking](#benchmarking) + ## Building To build Weld, you need [Rust 1.13 or higher](http://rust-lang.org) and [LLVM](http://llvm.org) 3.8. To install Rust, follow the steps [here](https://rustup.rs). You can verify that Rust was installed correctly on your system by typing `rustc` into your shell. -### MacOS Installation +#### MacOS LLVM Installation To install LLVM on macOS, first install [brew](https://brew.sh/). Then: @@ -23,22 +38,7 @@ $ ln -s /usr/local/bin/llvm-config-3.8 /usr/local/bin/llvm-config To make sure this worked correctly, run `llvm-config --version`. You should see `3.8.x`. -With LLVM and Rust installed, you can build Weld. Clone this repository and build using `cargo`: - -```bash -$ git clone https://www.github.com/weld-project/weld -$ cd weld/ -$ cargo build -``` - -Set the `WELD_HOME` environment variable and run tests: - -```bash -$ export WELD_HOME=/path/to/weld/directory -$ cargo test -``` - -### Ubuntu Installation +#### Ubuntu LLVM Installation To install LLVM on Ubuntu : @@ -55,21 +55,42 @@ $ ln -s /usr/bin/llvm-config-3.8 /usr/local/bin/llvm-config To make sure this worked correctly, run `llvm-config --version`. You should see `3.8.x`. -With LLVM and Rust installed, you can build Weld. Clone this repository and build using `cargo`: +#### Building Weld + +With LLVM and Rust installed, you can build Weld. Clone this repository, set the `WELD_HOME` environment variable, and build using `cargo`: ```bash $ git clone https://www.github.com/weld-project/weld $ cd weld/ +$ export WELD_HOME=`pwd` $ cargo build --release ``` -Set the `WELD_HOME` environment variable and run tests: +Weld builds two dynamically linked libraries (`.so` files on Linux and `.dylib` files on macOS): `libweld` and `libweldrt`. Both of these libraries must be on the `LD_LIBRARY_PATH`. By default, the libraries are in `$WELD_HOME/target/release` and `$WELD_HOME/weld_rt/target/release`. Set up the `LD_LIBRARY_PATH` as follows: + +```bash +$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$WELD_HOME/weld_rt/target/release:$WELD_HOME/target/release +``` + +Finally, run the unit and integration tests: ```bash -$ export WELD_HOME=/path/to/weld/directory $ cargo test ``` +## Documentation + +The `docs/` directory contains documentation for the different components of Weld. + +* [language.md](https://github.com/weld-project/weld/blob/master/docs/language.md) describes the syntax of the Weld IR. +* [api.md](https://github.com/weld-project/weld/blob/master/docs/api.md) describes the low-level C API for interfacing with Weld. +* [python.md](https://github.com/weld-project/weld/blob/master/docs/python.md) gives an overview of the Python API. +* [tutorial.md](https://github.com/weld-project/weld/blob/master/docs/tutorial.md) contains a tutorial for how to build a small vector library using Weld. + +## Grizzly + +**Grizzly** is a port of the [Pandas](pandas.pydata.org/) framework. Details on how to use Grizzly are under `python/grizzly`. + ## Running an Interactive REPL * `cargo test` runs unit and integration tests. A test name substring filter can be used to run a subset of the tests: @@ -117,5 +138,8 @@ Expression type: vec[i32] * `cargo bench` runs benchmarks under the `benches/` directory. The results of the benchmarks are written to a file called `benches.csv`. To specify specific benchmarks to run: ``` - cargo bench --bench benches -- -t + cargo bench [benchmark-name] ``` + + If a benchmark name is not provided, all benchmarks are run. + diff --git a/c/README.md b/c/README.md new file mode 100644 index 000000000..b3a321bdf --- /dev/null +++ b/c/README.md @@ -0,0 +1,17 @@ +# Weld C API + +This directory contains the C headers for the Weld API. + +To use in a C program: + +```C +#include "weld.h" +``` + +and when building: + +```bash +$ clang -lweld my_program.c +``` + +See the [API documentation](https://github.com/weld-project/weld/blob/master/docs/api.md) for details on the API. diff --git a/api/c/weld.h b/c/weld.h similarity index 94% rename from api/c/weld.h rename to c/weld.h index 586773c19..6a1461809 100644 --- a/api/c/weld.h +++ b/c/weld.h @@ -146,16 +146,22 @@ weld_conf_new(); * @param key the key to look up. * @return the string value for the key, or NULL if the key does not exist. */ -const char * -extern "C" weld_conf_get(weld_conf_t, const char *key); +extern "C" const char* +weld_conf_get(weld_conf_t, const char *key); /** Set a value for a Weld configuration key. * * @param key the key * @param key the value */ -void -extern "C" weld_conf_get(weld_conf_t, const char *key, const char *value); +extern "C" void +weld_conf_set(weld_conf_t, const char *key, const char *value); + +/** Free a Weld configuration. + * + */ +extern "C" weld_conf_t +weld_conf_free(weld_conf_t); #endif diff --git a/docs/api.md b/docs/api.md index ebe3aa756..6d383f360 100644 --- a/docs/api.md +++ b/docs/api.md @@ -204,16 +204,22 @@ weld_conf_new(); * @param key the key to look up. * @return the string value for the key, or NULL if the key does not exist. */ -const char * -extern "C" weld_conf_get(weld_conf_t, const char *key); +extern "C" const char * +weld_conf_set(weld_conf_t, const char *key); /** Set a value for a Weld configuration key. * * @param key the key * @param key the value */ -void -extern "C" weld_conf_get(weld_conf_t, const char *key, const char *value); +extern "C" void +weld_conf_get(weld_conf_t, const char *key, const char *value); + +/** Return a new Weld configuraiton. + * + */ +extern "C" void +weld_conf_free(weld_conf_t); ``` diff --git a/docs/python.md b/docs/python.md new file mode 100644 index 000000000..2815948a7 --- /dev/null +++ b/docs/python.md @@ -0,0 +1,59 @@ +# Python API + +The Python API is found under the `python/` directory. It provides convinient wrapper objects for the low-level C API, as well as utilities for building Weld computations and composing Python libraries. + +To use the Python API, set the `PYTHONPATH` environment variable so it can find the `weld` Python package: + +```bash +$ export PYTHONPATH=$PYTHONPATH:$WELD_HOME/python +``` + +You should also follow the setup instructions [here](https://github.com/weld-project/weld/blob/master/README.md) (in particular, build Weld and make sure its dynamic libraries are on the `LD_LIBRARY_PATH`). + +### Bindings + +The `weld.bindings` module contains bindings for the [C API](https://github.com/weld-project/weld/blob/master/docs/api.md). Each type in the C API is wrapped as a Python object. Methods on the Python objects call the corresponding C API functions. + +As an example, the code below creates a new `WeldConf`, sets a value on it, and then gets the value back: + +```python +>>> import weld.bindings as bnd +>>> conf = bnd.WeldConf() # calls weld_conf_new() +>>> conf.set("myKey", "myValue") # calls weld_conf_set(...) +>>> print conf.get("myKey") # calls weld_conf_get(...) +"myValue" +``` + +### WeldObject API + +The `WeldObject` API is included in the `weld.weldobject` module, and an example of how to use it is described [here](https://github.com/weld-project/weld/blob/master/docs/tutorial.md). + +This API provides an interface for _composing_ Python programs by building a lazily evaluated Weld computation. The `WeldObject` tracks values it operates over (called "dependencies") and builds and runs a runnable Weld module using a `evaluate` method. Dependencies are added using the `update` function. This function requires a Weld type for the dependency being added; types are available in the `weld.types` module. + +The table below describes the `WeldObject` API in brief: + + Method/Field | Description + ------------- | ------------- + `update(value, ty)` | Adds `value` (which has Weld type `ty`) in Weld as a dependency. Returns a string name which can be used in the object's Weld code to refer to this value. + `evaluate(ty)` | Evaluates the object and returns a value. `ty` is the expected Weld type of the return value. + `weld_code` | A string field representing the Weld IR for this object. This string is modified to register a computation with this object. See [this](https://github.com/weld-project/weld/blob/master/docs/language.md) document for a description of the language. + + +The general usage pattern for a WeldObject is to initialize it, add some dependencies and Weld code to register a computation, and then evaluate it to get a return value. Here's an example, where we add two numbers: + +```python +>>> import weld.weldobject as wo +>>> import weld.encoders as enc +>>> obj = wo.WeldObject(enc.WeldScalarEncoder(), enc.WeldScalarDecoder()) # See more about encoders below +>>> name1 = obj.update(1, WeldI32()) +>>> name2 = obj.update(2, WeldI32()) +>>> obj.weld_code = name1 + " + " + name2 # Weld IR to add two numbers. +``` + +### Encoders and Decoders + +When data is passed into Weld, it must be marshalled into a binary format which Weld understands (these formats are described in the [C API doc](https://github.com/weld-project/weld/blob/master/docs/api.md). In general, values are formatted using C scalars and structs; Python's `ctypes` module allows constructing these kinds of representations. + +To support custom formats, the `WeldObject` API takes an encoder, which allows encoding a Python object as a Weld object, and a decoder, which allows decoding a Weld object into a Python object. These encoders and decoders are interfaces which must be implemented by a library writer. + +Weld provides some commonly used encoders and decoders in the `weld.encoders` module. NumPy arrays, for example, are a common way to represent C-style arrays in Python. Weld thus includes a `WeldNumPyEncoder` and `WeldNumPyDecoder` class to marshall 1-dimensional NumPy arrays. diff --git a/easy_ll/src/lib.rs b/easy_ll/src/lib.rs index bb1d19989..8b7fc655d 100644 --- a/easy_ll/src/lib.rs +++ b/easy_ll/src/lib.rs @@ -115,9 +115,7 @@ pub fn load_library(libname: &str) -> Result<(), LlvmError> { /// Compile a string of LLVM IR (in human readable format) into a `CompiledModule` that can then /// be executed. The LLVM IR should contain an entry point function called `run` that takes `i64` /// and returns `i64`, which will be called by `CompiledModule::run`. -pub fn compile_module(code: &str, - static_lib_file: Option<&str>) - -> Result { +pub fn compile_module(code: &str, bc_file: Option<&[u8]>) -> Result { unsafe { // Initialize LLVM ONCE.call_once(|| initialize()); @@ -141,10 +139,10 @@ pub fn compile_module(code: &str, // Parse the IR to get an LLVMModuleRef let module = try!(parse_module_str(context, code)); - if static_lib_file != None { - let merger_module = try!(parse_module_file(context, static_lib_file.unwrap())); + if let Some(s) = bc_file { + let bc_module = try!(parse_module_bytes(context, s)); llvm::linker::LLVMLinkModules(module, - merger_module, + bc_module, llvm::linker::LLVMLinkerMode::LLVMLinkerDestroySource, std::ptr::null_mut()); } @@ -202,6 +200,25 @@ unsafe fn parse_module_helper(context: LLVMContextRef, Ok(module) } +/// Parse a buffer of IR bytecode into an `LLVMModuleRef` for the given context. +unsafe fn parse_module_bytes(context: LLVMContextRef, + code: &[u8]) + -> Result { + // Create an LLVM memory buffer around the code + let code_len = code.len(); + let name = try!(CString::new("module")); + let buffer = llvm::core::LLVMCreateMemoryBufferWithMemoryRange(code.as_ptr() as *const i8, + code_len, + name.as_ptr(), + 0); + + if buffer.is_null() { + return Err(LlvmError::new("LLVMCreateMemoryBufferWithMemoryRange failed")); + } + + parse_module_helper(context, buffer) +} + /// Parse a string of IR code into an `LLVMModuleRef` for the given context. unsafe fn parse_module_str(context: LLVMContextRef, code: &str) @@ -264,7 +281,6 @@ unsafe fn check_run_function(module: LLVMModuleRef) -> Result<(), LlvmError> { let run = CString::new("run").unwrap(); let func = llvm::core::LLVMGetNamedFunction(module, run.as_ptr()); if func.is_null() { - println!("EEEK"); return Err(LlvmError::new("No run function in module")); } let c_str = llvm::core::LLVMPrintTypeToString(llvm::core::LLVMTypeOf(func)); diff --git a/examples/cpp/add_repl/add_repl.cpp b/examples/cpp/add_repl/add_repl.cpp index a8da39e57..f51376358 100644 --- a/examples/cpp/add_repl/add_repl.cpp +++ b/examples/cpp/add_repl/add_repl.cpp @@ -10,17 +10,17 @@ int main() { // Compile Weld module. weld_error_t e = NULL; - weld_module_t m = weld_module_compile("|x:i64| x+5L", "configuration", &e); + weld_conf_t conf = weld_conf_new(); + weld_module_t m = weld_module_compile("|x:i64| x+5L", conf, &e); + weld_conf_free(conf); if (weld_error_code(e)) { const char *err = weld_error_message(e); printf("Error message: %s\n", err); + exit(1); } - // Create a Weld Object for the argument. - while(true) { - char buf[4096]; char *c; printf(">>> "); @@ -40,13 +40,15 @@ int main() { weld_value_t arg = weld_value_new(&input); // Run the module and get the result. - weld_value_t result = weld_module_run(m, arg, &e); + weld_conf_t conf = weld_conf_new(); + weld_value_t result = weld_module_run(m, conf, arg, &e); void *result_data = weld_value_data(result); printf("Answer: %lld\n", *(int64_t *)result_data); // Free the values. weld_value_free(result); weld_value_free(arg); + weld_conf_free(conf); } weld_error_free(e); diff --git a/examples/cpp/mem_mgmt/Makefile b/examples/cpp/mem_mgmt/Makefile deleted file mode 100644 index 2efb0e88c..000000000 --- a/examples/cpp/mem_mgmt/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -CC=clang++ -LDFLAGS=-L../../../../target/debug/ -LIBS=-lweld - -.PHONY: all clean - -all: - ${CC} ${LDFLAGS} ${LIBS} mem_mgmt.cpp -o run - -clean: - rm -rf run - diff --git a/examples/cpp/mem_mgmt/README.md b/examples/cpp/mem_mgmt/README.md deleted file mode 100644 index 84c91deeb..000000000 --- a/examples/cpp/mem_mgmt/README.md +++ /dev/null @@ -1 +0,0 @@ -Tests memory allocation by allocating a large array in a loop, and then freeing it. diff --git a/examples/cpp/mem_mgmt/mem_mgmt.cpp b/examples/cpp/mem_mgmt/mem_mgmt.cpp deleted file mode 100644 index 135e5a904..000000000 --- a/examples/cpp/mem_mgmt/mem_mgmt.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include - -#include -#include - -// Include the Weld API. -#include "../../../weld.h" - -struct vec { - int32_t *data; - int64_t length; -}; - -int main() { - const size_t LEN = 10000000; - - printf("sleeping before input allocation so memory can be observed..\n"); - //sleep(5); - - struct vec inp; - inp.data = (int32_t *)malloc(sizeof(int32_t) * LEN); - inp.length = LEN; - - printf("sleeping before module compilation so memory can be observed..\n"); - //sleep(5); - - // Compile Weld module. - weld_error_t e = NULL; - weld_module_t m = weld_module_compile("|x:vec[i32]| map(x, |e| e+1)", "configuration", &e); - - if (weld_error_code(e)) { - printf("Weld compile returned error: %s\n", weld_error_message(e)); - exit(1); - } - - weld_value_t arg = weld_value_new(&inp); - - printf("starting run loop...\n"); - //sleep(1); - - for (int i = 0; i < 5010; i++) { - weld_error_t e = NULL; - // This allocates some data. - weld_value_t res = weld_module_run(m, arg, &e); - - // This frees the value and all memory associated with the run that couldn't - // safely be freed before. - weld_value_free(res); - weld_error_free(e); - printf("%d\n", i); - } - - // Clean up other resources. - weld_error_free(e); - weld_value_free(arg); - weld_module_free(m); - - printf("sleeping before quit so memory can be observed..\n"); - //sleep(5); - - return 0; -} diff --git a/examples/python/add_repl/add_repl.py b/examples/python/add_repl/add_repl.py index 6f72b27bb..547a31892 100644 --- a/examples/python/add_repl/add_repl.py +++ b/examples/python/add_repl/add_repl.py @@ -2,16 +2,9 @@ import os import sys -home = os.environ.get("WELD_HOME") -if home is None: - home = "../../python/" -if home[-1] != "/": - home += "/" - -libpath = home + "api/python" -sys.path.append(libpath) - import ctypes + +# PYTHONPATH must contain $WELD_HOME/python from weld.bindings import * # Setup the Weld code we want to run. @@ -33,3 +26,7 @@ data = res_obj.data() res_value = ctypes.cast(data, ctypes.POINTER(ctypes.c_int64)).contents.value print res_value + + # Free the object and its underlying data. If we want python to track the + # data, we should first copy it's value out. + res_obj.free() diff --git a/python/README.md b/python/README.md index a1e5142a9..dbf4d8bf5 100644 --- a/python/README.md +++ b/python/README.md @@ -1,16 +1,14 @@ -This README file assumes for convenience that `WELD_HOME` is set to the `weld` root directory. +# Weld Python API +This directory contains the Weld Python API and the Grizzly implementation. -Prerequisites -============= +### Prerequisites -Build and run tests for Weld (the instructions for this are in `$WELD_HOME/README.md`). +Build and run tests for Weld (the instructions for this are in the main `README.md`). - -Setup -===== +### Setup To setup Weld's Python API, add the following to the `PYTHONPATH`: ```bash ->> export PYTHONPATH=$PYTHONPATH:/path/to/python # by default, $WELD_HOME/python +$ export PYTHONPATH=$PYTHONPATH:/path/to/python # by default, $WELD_HOME/python ``` diff --git a/python/grizzly/README.md b/python/grizzly/README.md index c820883e1..f64b633f6 100644 --- a/python/grizzly/README.md +++ b/python/grizzly/README.md @@ -1,15 +1,14 @@ +# Grizzly + This README file assumes for convenience that `WELD_HOME` is set to the `weld` root directory. -Prerequisites -============= +### Prerequisites -Build and run tests for Weld (the instructions for this are in `$WELD_HOME/README.md`). -Make sure the `PYTHONPATH` is set correctly as detailed in `$WELD_HOME/python/README.md`. +Build and run tests for Weld (the instructions for this are in `$WELD_HOME/README.md`). Make sure the `PYTHONPATH` is set correctly as detailed in `$WELD_HOME/python/README.md`. -Running Grizzly's Unit Tests -============================ +### Running Grizzly's Unit Tests To run unit tests, run the following: diff --git a/python/weld/bindings.py b/python/weld/bindings.py index d03ca4154..ffdd22fdb 100644 --- a/python/weld/bindings.py +++ b/python/weld/bindings.py @@ -8,19 +8,13 @@ import os import copy -# Load the library. -path = os.environ["WELD_HOME"] -if path[-1] != "/": - path += "/" -path += "target/release/libweld" - system = platform.system() if system == 'Linux': - path += ".so" + path = "libweld.so" elif system == 'Windows': - path += ".dll" + path = "libweld.dll" elif system == 'Darwin': - path += ".dylib" + path = "libweld.dylib" else: raise OSError("Unsupported platform {}", system) @@ -65,16 +59,26 @@ def __init__(self, value, assign=False): self.val = weld_value_new(value) else: self.val = value + self.freed = False + + def _check(self): + if self.freed: + raise ValueError("Attempted to use freed WeldValue") def data(self): + self._check() weld_value_data = weld.weld_value_data weld_value_data.argtypes = [c_weld_value] weld_value_data.restype = c_void_p return weld_value_data(self.val) - def __del__(self): - # TODO : Garbage Collection still needs to be done - return + def free(self): + self._check() + weld_value_free = weld.weld_value_free + weld_value_free.argtypes = [c_weld_value] + weld_value_free.restype = None + self.freed = True + return weld_value_free(self.val) class WeldConf(c_void_p): diff --git a/weld/bin/repl.rs b/weld/bin/repl.rs index ed6449dc8..219fe0263 100644 --- a/weld/bin/repl.rs +++ b/weld/bin/repl.rs @@ -22,7 +22,7 @@ use weld::pretty_print::*; use weld::type_inference::*; use weld::sir::ast_to_sir; use weld::util::load_runtime_library; -use weld::util::get_merger_lib_path; +use weld::util::MERGER_BC; enum ReplCommands { LoadFile, @@ -194,8 +194,7 @@ fn main() { continue; } - if let Err(ref e) = easy_ll::compile_module(&llvm_code, - Some(&get_merger_lib_path())) { + if let Err(ref e) = easy_ll::compile_module(&llvm_code, Some(MERGER_BC)) { println!("Error during LLVM compilation:\n{}\n", e); } else { println!("LLVM module compiled successfully\n"); diff --git a/weld/llvm.rs b/weld/llvm.rs index 38e2db2bc..d6ea9912a 100644 --- a/weld/llvm.rs +++ b/weld/llvm.rs @@ -23,7 +23,7 @@ use super::sir::Terminator::*; use super::transforms; use super::type_inference; use super::util::IdGenerator; -use super::util::get_merger_lib_path; +use super::util::MERGER_BC; #[cfg(test)] use super::parser::*; @@ -2154,7 +2154,7 @@ pub fn compile_program(program: &Program) -> WeldResult let sir_prog = try!(sir::ast_to_sir(&expr)); let mut gen = LlvmGenerator::new(); try!(gen.add_function_on_pointers("run", &sir_prog)); - Ok(try!(easy_ll::compile_module(&gen.result(), Some(&get_merger_lib_path())))) + Ok(try!(easy_ll::compile_module(&gen.result(), Some(MERGER_BC)))) } #[test] diff --git a/weld/util.rs b/weld/util.rs index f749bc16d..8fd571a06 100644 --- a/weld/util.rs +++ b/weld/util.rs @@ -10,9 +10,7 @@ use std::collections::HashMap; use super::ast::*; use super::ast::ExprKind::*; -use std::env; - -const WELD_HOME: &'static str = "WELD_HOME"; +pub const MERGER_BC: &'static [u8] = include_bytes!("../weld_rt/cpp/libparbuilder.bc"); /// Utility struct that can track and generate unique IDs and symbols for use in an expression. /// Each SymbolGenerator tracks the maximum ID used for every symbol name, and can be used to @@ -91,31 +89,9 @@ impl IdGenerator { } } -/// Returns the value of the WELD_HOME environment variable, -/// or an error if the variable is not set. -/// -/// The returned path has a trailing `/`. -pub fn get_weld_home() -> Result { - match env::var(WELD_HOME) { - Ok(path) => { - let path = if path.chars().last().unwrap() != '/' { - path + &"/" - } else { - path - }; - Ok(path) - } - Err(_) => Err(()), - } -} - /// Loads the Weld runtime library. pub fn load_runtime_library() -> Result<(), String> { - let weld_home = get_weld_home().unwrap_or(".".to_string()); - // TODO(shoumik): Is there a better way to do this? - let lib_path = "weld_rt/target/release/libweldrt"; - let path = format!("{}{}", weld_home, lib_path); - if let Err(_) = easy_ll::load_library(&path) { + if let Err(_) = easy_ll::load_library(&"libweldrt") { let err_message = unsafe { std::ffi::CStr::from_ptr(libc::dlerror()) }; let err_message = err_message.to_owned().into_string().unwrap(); Err(err_message) @@ -123,10 +99,3 @@ pub fn load_runtime_library() -> Result<(), String> { Ok(()) } } - -pub fn get_merger_lib_path() -> String { - let weld_home = get_weld_home().unwrap_or(".".to_string()); - // TODO(shoumik): Is there a better way to do this? - let lib_path = "weld_rt/cpp/libparbuilder.bc"; - format!("{}{}", weld_home, lib_path) -} diff --git a/weld_rt/Cargo.toml b/weld_rt/Cargo.toml index bfa182350..e128615da 100644 --- a/weld_rt/Cargo.toml +++ b/weld_rt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "weldrt" version = "0.1.0" -authors = ["Shoumik Palkar "] +authors = ["Weld Developers "] build = "build.rs" [dependencies] diff --git a/weld_rt/build.rs b/weld_rt/build.rs index 023f1687a..3191530eb 100644 --- a/weld_rt/build.rs +++ b/weld_rt/build.rs @@ -13,8 +13,19 @@ fn main() { let cpp_path = path + &"weld_rt/cpp"; - Command::new("make").arg("clean").arg("-C").arg(cpp_path.clone()).status().unwrap(); - Command::new("make").arg("-C").arg(cpp_path.clone()).status().unwrap(); + Command::new("make") + .arg("clean") + .arg("-C") + .arg(cpp_path.clone()) + .status() + .unwrap(); + + Command::new("make") + .arg("-C") + .arg(cpp_path.clone()) + .status() + .unwrap(); + println!("{}", format!("cargo:rustc-link-search=native={}", cpp_path)); let target = env::var("TARGET").unwrap(); @@ -23,8 +34,7 @@ fn main() { for lib in libs { println!("cargo:rustc-link-lib={}", lib); } - } - else if target == "x86_64-unknown-linux-gnu" { + } else if target == "x86_64-unknown-linux-gnu" { let libs = vec!["z", "stdc++"]; for lib in libs { println!("cargo:rustc-link-lib={}", lib);