1cmake_minimum_required(VERSION 3.12)
2project(wasmtime C)
3
4set(WASMTIME_USER_CARGO_BUILD_OPTIONS "" CACHE STRING "Additional cargo flags (such as --features) to apply to the build command")
5option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
6option(BUILD_TESTS "Build tests" OFF)
7option(WASMTIME_ALWAYS_BUILD "If cmake should always invoke cargo to build wasmtime" ON)
8option(WASMTIME_FASTEST_RUNTIME "Set flags designed to optimize runtime performance" OFF)
9set(WASMTIME_TARGET "" CACHE STRING "Rust target to build for")
10
11if(WASMTIME_TARGET STREQUAL "")
12  execute_process(COMMAND rustc -vV OUTPUT_VARIABLE RUSTC_VERSION)
13  string(REGEX MATCH "host: ([^ \n]*)" RUSTC_HOST ${RUSTC_VERSION})
14  string(STRIP ${CMAKE_MATCH_1} RUSTC_HOST_TARGET)
15  set(WASMTIME_TARGET ${RUSTC_HOST_TARGET})
16endif()
17
18include(cmake/features.cmake)
19
20if(WASMTIME_FASTEST_RUNTIME)
21  set(WASMTIME_BUILD_TYPE_FLAG "--profile=fastest-runtime")
22  set(WASMTIME_BUILD_TYPE "fastest-runtime")
23  set(CARGO_PROFILE_PANIC CARGO_PROFILE_RELEASE_PANIC)
24else()
25  if(CMAKE_BUILD_TYPE STREQUAL "Debug")
26    set(WASMTIME_BUILD_TYPE "debug")
27    set(CARGO_PROFILE_PANIC CARGO_PROFILE_DEBUG_PANIC)
28  else()
29    set(WASMTIME_BUILD_TYPE_FLAG "--release")
30    set(WASMTIME_BUILD_TYPE "release")
31    set(CARGO_PROFILE_PANIC CARGO_PROFILE_RELEASE_PANIC)
32  endif()
33endif()
34
35# Respect CARGO_TARGET_DIR if set, allowing users to customize where Cargo
36# outputs build artifacts
37if(DEFINED ENV{CARGO_TARGET_DIR})
38  set(WASMTIME_TARGET_DIR $ENV{CARGO_TARGET_DIR}/${WASMTIME_TARGET}/${WASMTIME_BUILD_TYPE})
39else()
40  set(WASMTIME_TARGET_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../target/${WASMTIME_TARGET}/${WASMTIME_BUILD_TYPE})
41endif()
42
43if(WASMTIME_TARGET MATCHES "apple")
44  set(WASMTIME_SHARED_FILES libwasmtime.dylib)
45  set(WASMTIME_STATIC_FILES libwasmtime.a)
46elseif(WASMTIME_TARGET MATCHES "windows-gnu")
47  set(WASMTIME_SHARED_FILES libwasmtime.dll.a wasmtime.dll)
48  set(WASMTIME_STATIC_FILES libwasmtime.a)
49elseif(WASMTIME_TARGET MATCHES "windows-msvc")
50  set(WASMTIME_SHARED_FILES wasmtime.dll.lib wasmtime.dll)
51  set(WASMTIME_STATIC_FILES wasmtime.lib)
52else()
53  set(WASMTIME_SHARED_FILES libwasmtime.so)
54  set(WASMTIME_STATIC_FILES libwasmtime.a)
55endif()
56
57list(TRANSFORM WASMTIME_SHARED_FILES PREPEND ${WASMTIME_TARGET_DIR}/)
58list(TRANSFORM WASMTIME_STATIC_FILES PREPEND ${WASMTIME_TARGET_DIR}/)
59
60list(APPEND WASMTIME_BUILD_ENV "${CARGO_PROFILE_PANIC}=abort")
61if (APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET)
62    # On macOS, we need to set the deployment target for the build
63    list(APPEND WASMTIME_BUILD_ENV "MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
64endif()
65
66include(ExternalProject)
67find_program(WASMTIME_CARGO_BINARY cargo)
68if(NOT WASMTIME_CARGO_BINARY)
69    message(FATAL_ERROR [["cargo" was not found. Ensure "cargo" is in PATH. Aborting...]])
70endif()
71ExternalProject_Add(
72    wasmtime-crate
73    DOWNLOAD_COMMAND ""
74    CONFIGURE_COMMAND ""
75    INSTALL_COMMAND "${WASMTIME_INSTALL_COMMAND}"
76    BUILD_COMMAND
77        ${CMAKE_COMMAND} -E env ${WASMTIME_BUILD_ENV}
78        ${WASMTIME_CARGO_BINARY} build
79          --target ${WASMTIME_TARGET}
80          --package wasmtime-c-api
81          ${WASMTIME_BUILD_TYPE_FLAG}
82          ${WASMTIME_FEATURES}
83          ${WASMTIME_USER_CARGO_BUILD_OPTIONS}
84    USES_TERMINAL_BUILD TRUE
85    # Note that this is used as the cwd for the cargo invocation itself, build
86    # byproducts go in the `target` directory at the top-level.
87    BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}
88    BUILD_ALWAYS ${WASMTIME_ALWAYS_BUILD}
89    BUILD_BYPRODUCTS ${WASMTIME_SHARED_FILES} ${WASMTIME_STATIC_FILES})
90add_library(wasmtime INTERFACE)
91add_dependencies(wasmtime wasmtime-crate)
92
93if(BUILD_SHARED_LIBS)
94    if(NOT WASMTIME_TARGET MATCHES "windows")
95      if(NOT WASMTIME_TARGET MATCHES "apple")
96        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
97      endif()
98    endif()
99    list(GET WASMTIME_SHARED_FILES 0 WASMTIME_SHARED_LIB_TO_LINK)
100    target_link_libraries(wasmtime INTERFACE ${WASMTIME_SHARED_LIB_TO_LINK})
101else()
102    if(WASMTIME_TARGET MATCHES "windows")
103        target_compile_options(wasmtime INTERFACE -DWASM_API_EXTERN= -DWASI_API_EXTERN=)
104        target_link_libraries(wasmtime INTERFACE ${WASMTIME_STATIC_FILES}
105            ws2_32 advapi32 userenv ntdll shell32 ole32 bcrypt)
106    elseif(WASMTIME_TARGET MATCHES "apple")
107        target_link_libraries(wasmtime INTERFACE ${WASMTIME_STATIC_FILES}
108            "-framework CoreFoundation")
109    else()
110        target_link_libraries(wasmtime INTERFACE ${WASMTIME_STATIC_FILES}
111            pthread dl m)
112    endif()
113endif()
114
115target_include_directories(wasmtime
116  INTERFACE include
117  INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/include)
118configure_file(include/wasmtime/conf.h.in include/wasmtime/conf.h)
119
120include(GNUInstallDirs)
121install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ TYPE INCLUDE)
122install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ TYPE INCLUDE
123        FILES_MATCHING REGEX "\\.hh?$")
124install(FILES ${WASMTIME_SHARED_FILES} ${WASMTIME_STATIC_FILES}
125        DESTINATION ${CMAKE_INSTALL_LIBDIR})
126
127if(WASMTIME_TARGET MATCHES "apple")
128  # Postprocess the macOS dylib a bit to have a more reasonable `LC_ID_DYLIB`
129  # directive than the default one that comes out of the linker when typically
130  # doing `cargo build`. For more info see #984
131  set(INSTALLED_LIB ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libwasmtime.dylib)
132  install(CODE "execute_process(COMMAND install_name_tool -id \"@rpath/libwasmtime.dylib\" ${INSTALLED_LIB})")
133endif()
134
135set(DOXYGEN_CONF_IN ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.conf.in)
136set(DOXYGEN_CONF_OUT ${CMAKE_BINARY_DIR}/doxygen.conf)
137configure_file(${DOXYGEN_CONF_IN} ${DOXYGEN_CONF_OUT})
138add_custom_target(doc
139    COMMAND doxygen ${DOXYGEN_CONF_OUT}
140    DEPENDS ${WASMTIME_GENERATED_CONF_H} ${DOXYGEN_CONF_OUT}
141    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
142
143if (NOT CMAKE_CXX_STANDARD)
144  message(STATUS "Cannot detect C++ Standard. Switching to C++17 by default !!")
145  set(CMAKE_CXX_STANDARD 17)
146endif()
147message(STATUS "CMAKE_CXX_STANDARD is ${CMAKE_CXX_STANDARD}")
148if (NOT CMAKE_CXX_STANDARD GREATER_EQUAL 17)
149  message(FATAL_ERROR "WASMTIME_CPP library does not support ${CMAKE_CXX_STANDARD}")
150endif()
151set(CMAKE_CXX_STANDARD_REQUIRED True)
152
153option(ENABLE_CODE_ANALYSIS "Run code analysis" OFF)
154message(STATUS "ENABLE_CODE_ANALYSIS       ${ENABLE_CODE_ANALYSIS}")
155
156if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
157   add_compile_options (-fdiagnostics-color=always)
158elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
159   add_compile_options (-fcolor-diagnostics)
160endif ()
161
162add_library(wasmtime-cpp INTERFACE)
163target_link_libraries(wasmtime-cpp INTERFACE wasmtime)
164if (MSVC)
165  target_compile_options(wasmtime-cpp INTERFACE /DWASM_API_EXTERN= /DWASI_API_EXTERN=)
166  target_link_libraries(wasmtime-cpp INTERFACE ws2_32 bcrypt advapi32 userenv ntdll shell32 ole32)
167else()
168  target_link_libraries(wasmtime-cpp INTERFACE stdc++ pthread)
169endif()
170
171if (BUILD_TESTS)
172  message(STATUS "Building tests")
173  set(CMAKE_CXX_STANDARD 20)
174
175  enable_language(CXX)
176  set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
177
178  enable_testing()
179  add_subdirectory(tests)
180endif()
181