Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasmtime: need to download binaries in build #7190

Merged
merged 6 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions recipes/wasmtime/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
from conans import ConanFile, CMake, tools
from conans.errors import ConanInvalidConfiguration, ConanException
from conans import ConanFile, tools
from conans.errors import ConanInvalidConfiguration
import os
import shutil

required_conan_version = ">=1.33.0"


class WasmtimeConan(ConanFile):
name = 'wasmtime'
homepage = 'https://github.com/bytecodealliance/wasmtime'
license = 'Apache-2.0'
url = 'https://github.com/conan-io/conan-center-index'
name = "wasmtime"
homepage = "https://github.com/bytecodealliance/wasmtime"
license = "Apache-2.0"
url = "https://github.com/conan-io/conan-center-index"
description = "Standalone JIT-style runtime for WebAssembly, using Cranelift"
topics = ("webassembly", "wasm", "wasi")
settings = "os", "compiler", "arch"
options = { "shared": [True, False] }
default_options = { 'shared': False }
settings = "os", "arch", "compiler"
options = {
"shared": [True, False],
}
default_options = {
"shared": False,
}
no_copy_source = True

@property
Expand All @@ -31,7 +36,7 @@ def _minimum_compilers_version(self):
}

@property
def _sources_key(self):
def _sources_os_key(self):
if self.settings.compiler == "Visual Studio":
return "Windows"
elif self.settings.os == "Windows" and self.settings.compiler == "gcc":
Expand Down Expand Up @@ -60,16 +65,23 @@ def validate(self):
self.output.warn(msg)

try:
self.conan_data["sources"][self.version][self._sources_key][str(self.settings.arch)]
self.conan_data["sources"][self.version][self._sources_os_key][str(self.settings.arch)]
except KeyError:
raise ConanInvalidConfiguration("Binaries for this combination of architecture/version/os not available")
raise ConanInvalidConfiguration("Binaries for this combination of architecture/version/os are not available")

if (self.settings.compiler, self.settings.os) == ("gcc", "Windows") and self.options.shared:
# FIXME: https://github.com/bytecodealliance/wasmtime/issues/3168
raise ConanInvalidConfiguration("Shared mingw is currently not possible")

def source(self):
tools.get(**self.conan_data["sources"][self.version][self._sources_key][str(self.settings.arch)], destination=self.source_folder, strip_root=True)
def package_id(self):
del self.info.settings.compiler.version
if self.settings.compiler == "clang":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it is dirty hack ??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a way to alias the packages of gcc and clang.
I couldn't remove self.info.settings.compiler.

I argue it's a clean hack 😛

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done it this way to avoid creating duplicate packages.
Packages with compiler=gcc and compiler=clang will be identical, because nothing is built.

If I understand compatible compiler correctly, then a package for gcc and clang will be created.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually used a custom package id: see https://docs.conan.io/en/latest/creating_packages/define_abi_compatibility.html#defining-a-custom-package-id

So not a hack after all. It's documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compatible packages would require me to list all gcc/clang versions that are compatible which does not exist, or will be always incomplete.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compatible compilers works, but it will cause c3i to generate a package for gcc and clang, which are the same.
So I'd prefer to keep the package_id method as it is now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, it will generate for both clang and gcc. Indeed using same pkg id will save cci resources.

self.info.settings.compiler = "gcc"

def build(self):
# This is packaging binaries so the download needs to be in build
tools.get(**self.conan_data["sources"][self.version][self._sources_os_key][str(self.settings.arch)],
destination=self.source_folder, strip_root=True)

def package(self):
shutil.copytree(os.path.join(self.source_folder, "include"),
Expand All @@ -86,7 +98,7 @@ def package(self):
self.copy("wasmtime.lib", src=srclibdir, dst="lib", keep_path=False)
self.copy("libwasmtime.a", src=srclibdir, dst="lib", keep_path=False)

self.copy('LICENSE', dst='licenses', src=self.source_folder)
self.copy("LICENSE", dst="licenses", src=self.source_folder)

def package_info(self):
if self.options.shared:
Expand All @@ -96,10 +108,10 @@ def package_info(self):
self.cpp_info.libs = ["wasmtime"]
else:
if self.settings.os == "Windows":
self.cpp_info.defines= ["/DWASM_API_EXTERN=", "/DWASI_API_EXTERN="]
self.cpp_info.defines = ["WASM_API_EXTERN=", "WASI_API_EXTERN="]
self.cpp_info.libs = ["wasmtime"]

if self.settings.os == 'Windows':
self.cpp_info.system_libs = ['ws2_32', 'bcrypt', 'advapi32', 'userenv', 'ntdll', 'shell32', 'ole32']
elif self.settings.os == 'Linux':
self.cpp_info.system_libs = ['pthread', 'dl', 'm']
if self.settings.os == "Windows":
self.cpp_info.system_libs = ["ws2_32", "bcrypt", "advapi32", "userenv", "ntdll", "shell32", "ole32"]
elif self.settings.os == "Linux":
self.cpp_info.system_libs = ["pthread", "dl", "m"]
14 changes: 6 additions & 8 deletions recipes/wasmtime/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
cmake_minimum_required(VERSION 3.1)
project(PackageTest C)

set(CMAKE_C_STANDARD 11)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not to use set(CMAKE_C_STANDARD 11) at top of file ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an idiom we adopted at cci.
"Modern CMake" is all about using targets and avoiding global variables.

It probably does not matter for such a small example, but most of us believe it's better to use best practices as much as possible.

project(test_package C)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
conan_basic_setup(TARGETS)

find_package(wasmtime REQUIRED)
find_package(wasmtime REQUIRED CONFIG)

add_executable(example example.c)
target_link_libraries(example PRIVATE wasmtime::wasmtime)
target_compile_options(example PRIVATE ${CONAN_COMPILE_DEFINITIONS_WASMTIME})
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE wasmtime::wasmtime)
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11)
8 changes: 4 additions & 4 deletions recipes/wasmtime/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import os


class WasmtimeTestConan(ConanFile):
settings = 'os', 'compiler', 'build_type', 'arch'
generators = 'cmake', 'cmake_find_package'
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package_multi"

def build(self):
cmake = CMake(self)
Expand All @@ -13,5 +13,5 @@ def build(self):

def test(self):
if not tools.cross_building(self):
bin_path = os.path.join('bin', 'example')
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)
8 changes: 0 additions & 8 deletions recipes/wasmtime/all/test_package/example.c

This file was deleted.

35 changes: 35 additions & 0 deletions recipes/wasmtime/all/test_package/test_package.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <wasmtime.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *wat = "(module\n"
"\t(func (param $lhs i32) (param $rhs i32) (result i32)\n"
"\t\tlocal.get $lhs\n"
"\t\tlocal.get $rhs\n"
"\t\ti32.add))";
wasm_byte_vec_t ret;
wasmtime_error_t *error = wasmtime_wat2wasm(wat, strlen(wat), &ret);
if (error != NULL) {
fprintf(stderr, "wasmtime_wat2wasm failed:\n");
wasm_name_t message;
wasmtime_error_message(error, &message);
wasmtime_error_delete(error);
fprintf(stderr, "%s\n", message.data);
wasm_byte_vec_delete(&message);
return EXIT_FAILURE;
}
printf("wasm text:\n%s\n", wat);
puts("assembly:");
for(size_t i = 0; i < ret.size; ++i) {
printf(" 0x%02x", ret.data[i]);
if (i%8 == 7) {
puts("");
}
}
puts("");
wasm_byte_vec_delete(&ret);
return EXIT_SUCCESS;
}