diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..30495bdb --- /dev/null +++ b/Makefile @@ -0,0 +1,60 @@ +# By default do a release build with moving immix +MMTK_MOVING ?= 1 +MMTK_PLAN ?= Immix +CURR_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +# Getting metadata about Julia repo from Cargo file +JULIA_GIT_URL= $(shell cargo read-manifest --manifest-path=$(CURR_PATH)/mmtk/Cargo.toml | python -c 'import json,sys; print(json.load(sys.stdin)["metadata"]["julia"]["julia_repo"])') +JULIA_VERSION= $(shell cargo read-manifest --manifest-path=$(CURR_PATH)/mmtk/Cargo.toml | python -c 'import json,sys; print(json.load(sys.stdin)["metadata"]["julia"]["julia_version"])') + +# If the Julia directory doesn't exist throw an error +# since we need it to generate the bindgen bindings +ifeq (${JULIA_PATH},) +$(error "JULIA_PATH must be set to generate Rust bindings") +endif + +MMTK_JULIA_DIR := $(CURR_PATH) + +PROJECT_DIRS := JULIA_PATH=$(JULIA_PATH) MMTK_JULIA_DIR=$(MMTK_JULIA_DIR) +MMTK_VARS := MMTK_PLAN=$(MMTK_PLAN) MMTK_MOVING=$(MMTK_MOVING) + +ifeq (${MMTK_PLAN},Immix) +CARGO_FEATURES = immix +else ifeq (${MMTK_PLAN},StickyImmix) +CARGO_FEATURES = stickyimmix +else +$(error "Unsupported MMTk plan: $(MMTK_PLAN)") +endif + +ifeq ($(MMTK_MOVING), 0) +CARGO_FEATURES := $(CARGO_FEATURES),non_moving +endif + +# Build the mmtk-julia project +# Note that we might need to clone julia if it doesn't exist +# since we need to run bindgen as part of building mmtk-julia +release: + @echo "Building the Rust project in $(MMTK_JULIA_DIR)mmtk"; + @cd $(MMTK_JULIA_DIR)mmtk && $(PROJECT_DIRS) cargo build --features $(CARGO_FEATURES) --release + +debug: + @echo "Building the Rust project in $(MMTK_JULIA_DIR) using a debug build"; + @cd $(MMTK_JULIA_DIR)mmtk && $(PROJECT_DIRS) cargo build --features $(CARGO_FEATURES) + +# Build the Julia project (which will build the binding as part of their deps build) +julia: + @echo "Building the Julia project in $(JULIA_PATH)"; + @cd $(JULIA_PATH) && $(PROJECT_DIRS) $(MMTK_VARS) make + +# Build the Julia project using a debug build (which will do a release build of the binding, unless MMTK_BUILD=debug) +julia-debug: + @echo "Building the Julia project in $(JULIA_PATH)"; + @cd $(JULIA_PATH) && $(PROJECT_DIRS) $(MMTK_VARS) make debug + +# Clean up the build artifacts +clean: + @echo "Cleaning up build artifacts in $(JULIA_PATH) and $(MMTK_JULIA_DIR)"; + @cd $(JULIA_PATH) && make clean + @cd $(MMTK_JULIA_DIR)mmtk && cargo clean + +.PHONY: release debug julia julia-debug clean diff --git a/mmtk/Cargo.toml b/mmtk/Cargo.toml index fd4b5e7d..ce7ef2c2 100644 --- a/mmtk/Cargo.toml +++ b/mmtk/Cargo.toml @@ -10,8 +10,8 @@ edition = "2018" # Metadata for the Julia repository [package.metadata.julia] # Our CI matches the following line and extract mmtk/julia. If this line is updated, please check ci yaml files and make sure it works. -julia_repo = "https://github.com/mmtk/julia.git" -julia_version = "b2f2d3c486739f20e4eb5500f3ad7b1866122fce" +julia_repo = "https://github.com/udesou/julia.git" +julia_version = "5f743032000a5ac85d18a64e3c6992e3b8e0f0bc" [lib] crate-type = ["cdylib"] diff --git a/mmtk/build.rs b/mmtk/build.rs index b8adc648..2f2a2342 100644 --- a/mmtk/build.rs +++ b/mmtk/build.rs @@ -1,4 +1,5 @@ extern crate bindgen; +use std::path::Path; // Use bindgen to build Rust bindings for Julia @@ -6,24 +7,42 @@ fn main() { // Use environment variable $JULIA_PATH that points to Julia folder let julia_dir_key = "JULIA_PATH"; let mmtk_dir_key = "MMTK_JULIA_DIR"; + let buildroot_dir_key = "JULIA_BUILDROOT"; let (mmtk_dir, julia_dir) = match (std::env::var(mmtk_dir_key), std::env::var(julia_dir_key)) { (Ok(mmtk_val), Ok(julia_val)) => (mmtk_val, julia_val), _ => panic!("Must set {} and {}", julia_dir_key, mmtk_dir_key), }; + // A build call from Julia's Makefile may build into a different directory + // e.g., via make O=/path-to-my-build/my-julia-build + // Check if JULIA_BUILD_ROOT is set and use it, otherwise, set it as the same dir as JULIA_PATH + let buildroot_dir = match std::env::var(buildroot_dir_key) { + Ok(buildroot_val) => buildroot_val, + _ => julia_dir.clone(), + }; + // running `make julia_version.h` in $JULIA_PATH/src to generate julia_version.h - std::process::Command::new("make") - .current_dir(format!("{}/src", julia_dir)) - .args(["julia_version.h"]) - .output() - .expect("failed to execute process"); + if !Path::new(format!("{}/src/julia_version.h", buildroot_dir).as_str()).exists() { + std::process::Command::new("make") + .current_dir(format!("{}/src", julia_dir)) + .env("BUILDDIR", buildroot_dir.clone()) + .args(["julia_version.h"]) + .output() + .expect("failed to execute process"); + } // runing `make` in $JULIA_PATH/deps to generate $JULIA_PATH/usr/include, in particular libunwind.h - std::process::Command::new("make") - .current_dir(format!("{}/deps", julia_dir)) - .output() - .expect("failed to execute process"); + // skip this process if that path already exists since + // the .h files could have already beeen generated when building via Makefile + if !Path::new(format!("{}/usr/include", buildroot_dir).as_str()).exists() { + std::process::Command::new("make") + .current_dir(format!("{}/deps", julia_dir)) + .env("BUILDDIR", buildroot_dir.clone()) + .env("MMTK_PLAN", "None") // Make sure this call doesn't try to compile the binding again + .output() + .expect("failed to execute process"); + } let bindings = bindgen::Builder::default() .header(format!("{}/src/julia.h", julia_dir)) @@ -36,7 +55,7 @@ fn main() { .clang_arg("-I") .clang_arg(format!("{}/src/support", julia_dir)) .clang_arg("-I") - .clang_arg(format!("{}/usr/include", julia_dir)) + .clang_arg(format!("{}/usr/include", buildroot_dir)) // all types that we generate bindings from .allowlist_item("jl_datatype_layout_t") .allowlist_item("jl_ucontext_t")