Skip to content

Commit

Permalink
Use cmake to build wasmtime-c-api (#9031)
Browse files Browse the repository at this point in the history
* Use cmake to build wasmtime-c-api

* Properly expose features when building via cmake

* Install all headers to same directory

* Add vets

* attempt to fix ci

* Run all tests on CI

prtest:full

* Set CARGO_BUILD_TARGET; add CMakeLists to package

* Update comment on github action

* Attempt to fix android build

* Fix source dir modifications of c-api build

* Re-add BINARY_DIR option

* Fix build

* Move header installation to a cmake script

Try to avoid dealing with cmake configuration/platforms/etc.

* Tweak build of headers

* Install headers in build dir for examples

* Add cmake files to dist, fix header install dir

---------

Co-authored-by: Alex Crichton <alex@alexcrichton.com>
  • Loading branch information
CGamesPlay and alexcrichton authored Aug 9, 2024
1 parent e6c532f commit 22a4480
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 77 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ semver = { version = "1.0.17", default-features = false }
# in configuring binary size and or exploring the binary size implications of
# various features. Most features are enabled by default but most embeddings
# likely won't need all features.
#
# When adding or removing a feature, make sure to kepe the C API in sync by
# modifying locations marked WASMTIME_FEATURE_LIST
[features]
default = [
# All subcommands are included by default.
Expand Down
76 changes: 17 additions & 59 deletions crates/c-api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,7 @@ if(WASMTIME_TARGET STREQUAL "")
set(WASMTIME_TARGET ${RUSTC_HOST_TARGET})
endif()

set(WASMTIME_FEATURES "--no-default-features")

option(WASMTIME_DISABLE_ALL_FEATURES
"disable all features by default instead of enabling them"
OFF)

macro(feature rust_name default)
string(TOUPPER "wasmtime_feature_${rust_name}" cmake_name)
string(REPLACE "-" "_" cmake_name ${cmake_name})
if(${default})
if(${WASMTIME_DISABLE_ALL_FEATURES})
set(feature_default OFF)
else()
set(feature_default ON)
endif()
else()
set(feature_default OFF)
endif()

option(${cmake_name} "enable the Cargo feature ${rust_name}" ${feature_default})

if(${cmake_name})
list(APPEND WASMTIME_FEATURES "--features=${rust_name}")
message(STATUS "Enabling feature ${rust_name}")
endif()
endmacro()

feature(profiling ON)
feature(wat ON)
feature(cache ON)
feature(parallel-compilation ON)
feature(wasi ON)
feature(logging ON)
feature(disable-logging OFF)
feature(coredump ON)
feature(addr2line ON)
feature(demangle ON)
feature(threads ON)
feature(gc ON)
feature(async ON)
feature(cranelift ON)
feature(winch ON)
# ... if you add a line above this be sure to also change:
#
# crates/c-api/include/wasmtime/conf.h.in
# crates/c-api/artifact/Cargo.toml
include(cmake/features.cmake)

if(WASMTIME_FASTEST_RUNTIME)
set(WASMTIME_BUILD_TYPE_FLAG "--profile=fastest-runtime")
Expand Down Expand Up @@ -109,11 +64,14 @@ ExternalProject_Add(
${CMAKE_COMMAND} -E env ${CARGO_PROFILE_PANIC}=abort
${WASMTIME_CARGO_BINARY} build
--target ${WASMTIME_TARGET}
--package wasmtime-c-api
${WASMTIME_BUILD_TYPE_FLAG}
${WASMTIME_FEATURES}
${WASMTIME_USER_CARGO_BUILD_OPTIONS}
USES_TERMINAL_BUILD TRUE
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/artifact
# Note that this is used as the cwd for the cargo invocation itself, build
# byproducts go in the `target` directory at the top-level.
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}
BUILD_ALWAYS ${WASMTIME_ALWAYS_BUILD}
BUILD_BYPRODUCTS ${WASMTIME_SHARED_FILES} ${WASMTIME_STATIC_FILES})
add_library(wasmtime INTERFACE)
Expand All @@ -138,21 +96,12 @@ else()
endif()
endif()

target_include_directories(wasmtime INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)

set(WASMTIME_GENERATED_CONF_H ${CMAKE_BINARY_DIR}/include/wasmtime/conf.h)
target_include_directories(wasmtime INTERFACE ${CMAKE_BINARY_DIR}/include)

configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/wasmtime/conf.h.in
${WASMTIME_GENERATED_CONF_H})
set(WASMTIME_HEADER_DST ${CMAKE_BINARY_DIR}/include)
include(cmake/install-headers.cmake)

include(GNUInstallDirs)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING REGEX "\\.hh?$")
install(FILES ${WASMTIME_GENERATED_CONF_H}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wasmtime)
install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install-headers.cmake)
install(FILES ${WASMTIME_SHARED_FILES} ${WASMTIME_STATIC_FILES}
DESTINATION ${CMAKE_INSTALL_LIBDIR})

Expand All @@ -171,3 +120,12 @@ add_custom_target(doc
COMMAND doxygen ${DOXYGEN_CONF_OUT}
DEPENDS ${WASMTIME_GENERATED_CONF_H} ${DOXYGEN_CONF_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_dependencies(doc headers-to-doc)

file(GLOB headers "include/*.h")
add_custom_target(headers-to-doc
COMMAND
${CMAKE_COMMAND}
-DWASMTIME_HEADER_DST=${CMAKE_BINARY_DIR}/include
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install-headers.cmake
DEPENDS ${headers})
8 changes: 4 additions & 4 deletions crates/c-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repository = "https://github.com/bytecodealliance/wasmtime"
readme = "README.md"
edition.workspace = true
links = "wasmtime-c-api"
include = ["include", "src", "build.rs"]
include = ["include", "src", "build.rs", "CMakeLists.txt", "cmake", "doxygen.conf.in"]

[lints]
workspace = true
Expand Down Expand Up @@ -39,6 +39,7 @@ wasmtime-wasi = { workspace = true, optional = true, features = ["preview1"] }
futures = { workspace = true, optional = true }

[features]
# WASMTIME_FEATURE_LIST
async = ['wasmtime/async', 'futures']
profiling = ["wasmtime/profiling"]
cache = ["wasmtime/cache"]
Expand All @@ -53,6 +54,5 @@ threads = ["wasmtime/threads"]
gc = ["wasmtime/gc"]
cranelift = ['wasmtime/cranelift']
winch = ['wasmtime/winch']
# ... if you add a line above this be sure to also change:
#
# crates/c-api/artifact/Cargo.toml
# ... if you add a line above this be sure to change the other locations
# marked WASMTIME_FEATURE_LIST
1 change: 0 additions & 1 deletion crates/c-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ fn main() {
// Wasm C API headers.
cfg
.include(std::env::var("DEP_WASMTIME_C_API_INCLUDE").unwrap());
.include(std::env::var("DEP_WASMTIME_C_API_WASM_INCLUDE").unwrap());

// Compile your C code.
cfg
Expand Down
7 changes: 3 additions & 4 deletions crates/c-api/artifact/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ doctest = false
wasmtime-c-api = { path = '..', package = 'wasmtime-c-api-impl' }

[features]
# WASMTIME_FEATURE_LIST
default = [
'profiling',
'wat',
Expand All @@ -34,10 +35,8 @@ default = [
'gc',
'cranelift',
'winch',
# ... if you add a line above this be sure to also change:
#
# crates/c-api/CMakeLists.txt
# crates/c-api/Cargo.toml
# ... if you add a line above this be sure to change the other locations
# marked WASMTIME_FEATURE_LIST
]
async = ['wasmtime-c-api/async']
profiling = ["wasmtime-c-api/profiling"]
Expand Down
45 changes: 43 additions & 2 deletions crates/c-api/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,45 @@
use std::env;
use std::process::Command;

// WASMTIME_FEATURE_LIST
const FEATURES: &[&str] = &[
"ASYNC",
"PROFILING",
"CACHE",
"PARALLEL_COMPILATION",
"WASI",
"LOGGING",
"DISABLE_LOGGING",
"COREDUMP",
"ADDR2LINE",
"DEMANGLE",
"THREADS",
"GC",
"CRANELIFT",
"WINCH",
];
// ... if you add a line above this be sure to change the other locations
// marked WASMTIME_FEATURE_LIST

fn main() {
let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
println!("cargo:include={dir}/include");
println!("cargo:rerun-if-changed=cmake/features.cmake");
println!("cargo:rerun-if-changed=cmake/install-headers.cmake");
println!("cargo:rerun-if-changed=include");

let out_dir = std::env::var("OUT_DIR").unwrap();
let mut cmake = Command::new("cmake");
cmake.arg("-DWASMTIME_DISABLE_ALL_FEATURES=ON");
cmake.arg(format!("-DCMAKE_INSTALL_PREFIX={out_dir}"));
for f in FEATURES {
if env::var_os(format!("CARGO_FEATURE_{f}")).is_some() {
cmake.arg(format!("-DWASMTIME_FEATURE_{f}=ON"));
}
}

cmake.arg("-P").arg("cmake/install-headers.cmake");

let status = cmake.status().expect("failed to spawn `cmake`");
assert!(status.success());

println!("cargo:include={out_dir}/include");
}
45 changes: 45 additions & 0 deletions crates/c-api/cmake/features.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
set(WASMTIME_FEATURES "--no-default-features")

option(WASMTIME_DISABLE_ALL_FEATURES
"disable all features by default instead of enabling them"
OFF)

macro(feature rust_name default)
string(TOUPPER "wasmtime_feature_${rust_name}" cmake_name)
string(REPLACE "-" "_" cmake_name ${cmake_name})
if(${default})
if(${WASMTIME_DISABLE_ALL_FEATURES})
set(feature_default OFF)
else()
set(feature_default ON)
endif()
else()
set(feature_default OFF)
endif()

option(${cmake_name} "enable the Cargo feature ${rust_name}" ${feature_default})

if(${cmake_name})
list(APPEND WASMTIME_FEATURES "--features=${rust_name}")
message(STATUS "Enabling feature ${rust_name}")
endif()
endmacro()

# WASMTIME_FEATURE_LIST
feature(profiling ON)
feature(wat ON)
feature(cache ON)
feature(parallel-compilation ON)
feature(wasi ON)
feature(logging ON)
feature(disable-logging OFF)
feature(coredump ON)
feature(addr2line ON)
feature(demangle ON)
feature(threads ON)
feature(gc ON)
feature(async ON)
feature(cranelift ON)
feature(winch ON)
# ... if you add a line above this be sure to change the other locations
# marked WASMTIME_FEATURE_LIST
17 changes: 17 additions & 0 deletions crates/c-api/cmake/install-headers.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.12)

include(${CMAKE_CURRENT_LIST_DIR}/features.cmake)

if(WASMTIME_HEADER_DST)
set(dst "${WASMTIME_HEADER_DST}")
else()
set(dst "${CMAKE_INSTALL_PREFIX}/include")
endif()
set(include_src "${CMAKE_CURRENT_LIST_DIR}/../include")

message(STATUS "Installing: ${dst}/wasmtime/conf.h")
file(READ "${include_src}/wasmtime/conf.h.in" conf_h)
file(CONFIGURE OUTPUT "${dst}/wasmtime/conf.h" CONTENT "${conf_h}")
file(INSTALL "${include_src}/"
DESTINATION "${dst}"
FILES_MATCHING REGEX "\\.hh?$")
4 changes: 2 additions & 2 deletions crates/c-api/doxygen.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.

INPUT = include @CMAKE_BINARY_DIR@/include
INPUT = @CMAKE_BINARY_DIR@/include

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
Expand Down Expand Up @@ -2162,7 +2162,7 @@ SEARCH_INCLUDES = YES
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.

INCLUDE_PATH = include @CMAKE_BINARY_DIR@/include
INCLUDE_PATH = @CMAKE_BINARY_DIR@/include

# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
Expand Down
10 changes: 5 additions & 5 deletions crates/c-api/include/wasmtime/async.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@
* are three mechanisms for yielding control from wasm to the caller: fuel,
* epochs, and async host functions.
*
* When WebAssembly is executed, a #wasmtime_call_future_t is returned. This
* When WebAssembly is executed, a `wasmtime_call_future_t` is returned. This
* struct represents the state of the execution and each call to
* #wasmtime_call_future_poll will execute the WebAssembly code on a separate
* `wasmtime_call_future_poll` will execute the WebAssembly code on a separate
* stack until the function returns or yields control back to the caller.
*
* It's expected these futures are pulled in a loop until completed, at which
* point the future should be deleted. Functions that return a
* #wasmtime_call_future_t are special in that all parameters to that function
* `wasmtime_call_future_t` are special in that all parameters to that function
* should not be modified in any way and must be kept alive until the future is
* deleted. This includes concurrent calls for a single store - another function
* on a store should not be called while there is a #wasmtime_call_future_t
* on a store should not be called while there is a `wasmtime_call_future_t`
* alive.
*
* As for asynchronous host calls - the reverse contract is upheld. Wasmtime
* will keep all parameters to the function alive and unmodified until the
* #wasmtime_func_async_continuation_callback_t returns true.
* `wasmtime_func_async_continuation_callback_t` returns true.
*
*/

Expand Down
3 changes: 3 additions & 0 deletions crates/c-api/include/wasmtime/conf.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef WASMTIME_CONF_H
#define WASMTIME_CONF_H

// WASMTIME_FEATURE_LIST
#cmakedefine WASMTIME_FEATURE_PROFILING
#cmakedefine WASMTIME_FEATURE_WAT
#cmakedefine WASMTIME_FEATURE_CACHE
Expand All @@ -22,6 +23,8 @@
#cmakedefine WASMTIME_FEATURE_ASYNC
#cmakedefine WASMTIME_FEATURE_CRANELIFT
#cmakedefine WASMTIME_FEATURE_WINCH
// ... if you add a line above this be sure to change the other locations
// marked WASMTIME_FEATURE_LIST

#if defined(WASMTIME_FEATURE_CRANELIFT) || defined(WASMTIME_FEATURE_WINCH)
#define WASMTIME_FEATURE_COMPILER
Expand Down

0 comments on commit 22a4480

Please sign in to comment.