blob: 72708991a63aafb6a40e57d61b67e7d3f4388508 [file] [log] [blame]
#
# Copyright 2016 WebAssembly Community Group participants
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
cmake_minimum_required(VERSION 2.6)
project(WABT)
option(BUILD_TESTS "Build GTest-based tests" ON)
option(RUN_BISON "Run bison" ON)
option(RUN_RE2C "Run re2c" ON)
option(USE_ASAN "Use address sanitizer" OFF)
option(USE_MSAN "Use memory sanitizer" OFF)
option(USE_LSAN "Use leak sanitizer" OFF)
option(USE_UBSAN "Use undefined behavior sanitizer" OFF)
option(CODE_COVERAGE "Build with code coverage enabled" OFF)
if (${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
set(COMPILER_IS_CLANG 1)
set(COMPILER_IS_GNU 0)
set(COMPILER_IS_MSVC 0)
elseif (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
set(COMPILER_IS_CLANG 0)
set(COMPILER_IS_GNU 1)
set(COMPILER_IS_MSVC 0)
elseif (${CMAKE_C_COMPILER_ID} STREQUAL "MSVC")
set(COMPILER_IS_CLANG 0)
set(COMPILER_IS_GNU 0)
set(COMPILER_IS_MSVC 1)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
set(COMPILER_IS_CLANG 1)
set(COMPILER_IS_GNU 0)
set(COMPILER_IS_MSVC 0)
else ()
set(COMPILER_IS_CLANG 0)
set(COMPILER_IS_GNU 0)
set(COMPILER_IS_MSVC 0)
endif ()
include(CheckIncludeFile)
include(CheckSymbolExists)
check_include_file("alloca.h" HAVE_ALLOCA_H)
check_include_file("unistd.h" HAVE_UNISTD_H)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
check_symbol_exists(sysconf "unistd.h" HAVE_SYSCONF)
check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP)
if (EMSCRIPTEN)
set(SIZEOF_SSIZE_T 4)
set(SIZEOF_SIZE_T 4)
set(SIZEOF_INT 4)
set(SIZEOF_LONG 4)
set(SIZEOF_LONG_LONG 8)
else ()
include(CheckTypeSize)
check_type_size(ssize_t SSIZE_T)
check_type_size(size_t SIZEOF_SIZE_T)
check_type_size(int SIZEOF_INT BUILTIN_TYPES_ONLY)
check_type_size(long SIZEOF_LONG BUILTIN_TYPES_ONLY)
check_type_size("long long" SIZEOF_LONG_LONG BUILTIN_TYPES_ONLY)
endif ()
configure_file(
${WABT_SOURCE_DIR}/src/config.h.in
${WABT_BINARY_DIR}/config.h
)
include_directories(src ${WABT_BINARY_DIR})
include_directories(third_party/jsoncpp)
if (COMPILER_IS_MSVC)
# disable warning C4018: signed/unsigned mismatch
# disable warning C4056, C4756: overflow in floating-point constant arithmetic
# seems to not like float compare w/ HUGE_VALF; bug?
# disable warnings C4267 and C4244: conversion/truncation from larger to smaller type.
# disable warning C4800: implicit conversion from larger int to bool
add_definitions(-W3 -wd4018 -wd4056 -wd4756 -wd4267 -wd4244 -wd4800 -WX -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)
else ()
# disable -Wunused-parameter: this is really common when implementing
# interfaces, etc.
# disable -Wpointer-arith: this is a GCC extension, and doesn't work in MSVC.
add_definitions(
-Wall -Wextra -Werror -Wno-unused-parameter -Wpointer-arith -g -std=c++11
-Wold-style-cast
)
# Need to define __STDC_*_MACROS because C99 specifies that C++ shouldn't
# define format (e.g. PRIu64) or limit (e.g. UINT32_MAX) macros without the
# definition, and some libcs (e.g. glibc2.17 and earlier) follow that.
add_definitions(-D__STDC_LIMIT_MACROS=1 -D__STDC_FORMAT_MACROS=1)
if (MINGW)
# _POSIX is needed to ensure we use mingw printf
# instead of the VC runtime one.
add_definitions(-D_POSIX)
endif ()
if (COMPILER_IS_GNU)
# disable -Wclobbered: it seems to be guessing incorrectly about a local
# variable being clobbered by longjmp.
add_definitions(-Wno-clobbered)
endif ()
if (NOT EMSCRIPTEN)
# try to get the target architecture by compiling a dummy.c file and
# checking the architecture using the file command.
file(WRITE ${WABT_BINARY_DIR}/dummy.c "main(){}")
try_compile(
COMPILE_OK
${WABT_BINARY_DIR}
${WABT_BINARY_DIR}/dummy.c
COPY_FILE ${WABT_BINARY_DIR}/dummy
)
if (COMPILE_OK)
execute_process(
COMMAND file ${WABT_BINARY_DIR}/dummy
RESULT_VARIABLE FILE_RESULT
OUTPUT_VARIABLE FILE_OUTPUT
ERROR_QUIET
)
if (FILE_RESULT EQUAL 0)
if (${FILE_OUTPUT} MATCHES "x86[-_]64")
set(TARGET_ARCH "x86-64")
elseif (${FILE_OUTPUT} MATCHES "Intel 80386")
set(TARGET_ARCH "i386")
elseif (${FILE_OUTPUT} MATCHES "ARM")
set(TARGET_ARCH "ARM")
else ()
message(WARNING "Unknown target architecture!")
endif ()
else ()
message(WARNING "Error running file on dummy executable")
endif ()
else ()
message(WARNING "Error compiling dummy.c file")
endif ()
if (TARGET_ARCH STREQUAL "i386")
# wasm doesn't allow for x87 floating point math
add_definitions(-msse2 -mfpmath=sse)
endif ()
endif ()
endif ()
set(USE_SANITIZER FALSE)
function(SANITIZER NAME FLAGS)
if (${NAME})
message("HERE ${NAME} ${FLAGS}")
if (USE_SANITIZER)
message(FATAL_ERROR "Only one sanitizer allowed")
endif()
set(USE_SANITIZER TRUE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}" PARENT_SCOPE)
endif ()
endfunction()
SANITIZER(USE_ASAN "-fsanitize=address")
SANITIZER(USE_MSAN "-fsanitize=memory")
SANITIZER(USE_LSAN "-fsanitize=leak")
SANITIZER(USE_UBSAN "-fsanitize=undefined -fno-sanitize-recover")
find_package(BISON 3.0)
if (RUN_BISON AND BISON_FOUND)
set(WAST_PARSER_GEN_CC ${WABT_BINARY_DIR}/wast-parser-gen.cc)
BISON_TARGET(WAST_PARSER_GEN_CC
${WABT_SOURCE_DIR}/src/wast-parser.y
${WAST_PARSER_GEN_CC}
COMPILE_FLAGS --defines=${WABT_BINARY_DIR}/wast-parser-gen.hh
)
else ()
set(WAST_PARSER_GEN_CC src/prebuilt/wast-parser-gen.cc)
include_directories(src/prebuilt)
endif ()
if (COMPILER_IS_CLANG OR COMPILER_IS_GNU)
# yyerror passes a non-string-literal to a printf-like function, which is a
# warning.
set_source_files_properties(
${WAST_PARSER_GEN_CC}
PROPERTIES
COMPILE_FLAGS "-Wno-format-security -Wno-old-style-cast"
)
endif ()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${WABT_SOURCE_DIR}/cmake)
find_package(RE2C 0.13)
if (RUN_RE2C AND RE2C_EXECUTABLE)
set(WAST_LEXER_CC ${WABT_SOURCE_DIR}/src/wast-lexer.cc)
set(WAST_LEXER_GEN_CC ${WABT_BINARY_DIR}/wast-lexer-gen.cc)
RE2C_TARGET(
NAME WAST_LEXER_GEN_CC
INPUT ${WAST_LEXER_CC}
OUTPUT ${WAST_LEXER_GEN_CC}
OPTIONS -bc
)
else ()
set(WAST_LEXER_GEN_CC src/prebuilt/wast-lexer-gen.cc)
endif ()
add_custom_target(everything)
add_library(libwabt STATIC
src/opcode.cc
src/binary-error-handler.cc
src/source-error-handler.cc
src/hash-util.cc
src/string-view.cc
src/ir.cc
src/wast-parser-lexer-shared.cc
${WAST_LEXER_GEN_CC}
${WAST_PARSER_GEN_CC}
src/type-checker.cc
src/validator.cc
src/binary-reader.cc
src/binary-reader-logging.cc
src/binary-writer.cc
src/binary-writer-spec.cc
src/binary-reader-ir.cc
src/binding-hash.cc
src/wat-writer.cc
src/interpreter.cc
src/binary-reader-interpreter.cc
src/apply-names.cc
src/generate-names.cc
src/resolve-names.cc
src/binary.cc
src/common.cc
src/config.cc
src/literal.cc
src/option-parser.cc
src/stream.cc
src/writer.cc
src/source-maps.cc
)
set_target_properties(libwabt PROPERTIES OUTPUT_NAME wabt)
add_library(libjsoncpp STATIC
third_party/jsoncpp/jsoncpp.cpp
)
set_target_properties(libjsoncpp PROPERTIES OUTPUT_NAME jsoncpp)
if (COMPILER_IS_CLANG OR COMPILER_IS_GNU)
target_compile_options(libjsoncpp PRIVATE "-Wno-old-style-cast")
endif ()
if (NOT EMSCRIPTEN)
if (CODE_COVERAGE)
add_definitions("-fprofile-arcs -ftest-coverage")
link_libraries(gcov)
endif ()
function(wabt_executable name)
# ARGV contains all arguments; remove the first one, ${name}, so it's just
# a list of sources.
list(REMOVE_AT ARGV 0)
add_executable(${name} ${ARGV})
add_dependencies(everything ${name})
target_link_libraries(${name} libwabt libjsoncpp)
set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
set_property(TARGET ${name} PROPERTY CXX_STANDARD_REQUIRED ON)
list(APPEND WABT_EXECUTABLES ${name})
set(WABT_EXECUTABLES ${WABT_EXECUTABLES} PARENT_SCOPE)
endfunction()
# wast2wasm
wabt_executable(wast2wasm src/tools/wast2wasm.cc)
# wasm2wast
wabt_executable(wasm2wast src/tools/wasm2wast.cc)
# wasmopcodecnt
wabt_executable(wasmopcodecnt
src/tools/wasmopcodecnt.cc src/binary-reader-opcnt.cc)
# wasmdump
wabt_executable(wasmdump src/tools/wasmdump.cc src/binary-reader-objdump.cc)
# wasm-link
wabt_executable(wasm-link src/tools/wasm-link.cc src/binary-reader-linker.cc)
# wasm-interp
wabt_executable(wasm-interp src/tools/wasm-interp.cc)
if (COMPILER_IS_CLANG OR COMPILER_IS_GNU)
target_link_libraries(wasm-interp m)
endif ()
# wast-desugar
wabt_executable(wast-desugar src/tools/wast-desugar.cc)
# symlinks for wast2wasm and wasm2wast
if (NOT WIN32)
add_custom_command(
TARGET wast2wasm
POST_BUILD
COMMAND ln -sf wast2wasm sexpr-wasm
)
add_custom_command(
TARGET wasm2wast
POST_BUILD
COMMAND ln -sf wasm2wast wasm-wast
)
endif ()
set_property(
DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"sexpr-wasm" "wasm-wast")
find_package(Threads)
if (BUILD_TESTS)
if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gtest/googletest)
message(FATAL_ERROR "Can't find third_party/gtest. Run git submodule update --init, or disable with CMake -DBUILD_TESTS=OFF.")
endif ()
include_directories(
third_party/gtest/googletest
third_party/gtest/googletest/include
)
# gtest
add_library(libgtest STATIC
third_party/gtest/googletest/src/gtest-all.cc
)
# hexfloat-test
set(HEXFLOAT_TEST_SRCS
src/literal.cc
test/hexfloat.cc
third_party/gtest/googletest/src/gtest_main.cc
)
add_executable(hexfloat_test ${HEXFLOAT_TEST_SRCS})
add_dependencies(everything hexfloat_test)
target_link_libraries(hexfloat_test libgtest ${CMAKE_THREAD_LIBS_INIT})
set_property(TARGET hexfloat_test PROPERTY CXX_STANDARD 11)
set_property(TARGET hexfloat_test PROPERTY CXX_STANDARD_REQUIRED ON)
# wabt-unittests
set(UNITTESTS_SRCS
src/test-string-view.cc
src/test-source-maps.cc
third_party/gtest/googletest/src/gtest_main.cc
)
wabt_executable(wabt-unittests ${UNITTESTS_SRCS})
target_link_libraries(wabt-unittests libgtest libjsoncpp ${CMAKE_THREAD_LIBS_INIT})
endif ()
# test running
find_package(PythonInterp 2.7 REQUIRED)
set(RUN_TESTS_PY ${WABT_SOURCE_DIR}/test/run-tests.py)
add_custom_target(run-tests
COMMAND ${PYTHON_EXECUTABLE} ${RUN_TESTS_PY} --bindir ${CMAKE_BINARY_DIR}
DEPENDS ${WABT_EXECUTABLES}
WORKING_DIRECTORY ${WABT_SOURCE_DIR}
)
# install
install(TARGETS ${WABT_EXECUTABLES} DESTINATION bin)
else ()
# emscripten stuff
# just dump everything into one binary so we can reference it from JavaScript
add_definitions(-Wno-warn-absolute-paths)
add_executable(libwabtjs src/emscripten-helpers.cc)
add_dependencies(everything libwabtjs)
target_link_libraries(libwabtjs libwabt)
set_target_properties(libwabtjs PROPERTIES OUTPUT_NAME libwabt)
set(WABT_JS ${WABT_SOURCE_DIR}/src/wabt.js)
set(EMSCRIPTEN_EXPORTED_JSON ${WABT_SOURCE_DIR}/src/emscripten-exported.json)
set(LIBWABT_LINK_FLAGS
--memory-init-file 0
--pre-js ${WABT_JS}
-s EXPORTED_FUNCTIONS=\"@${EMSCRIPTEN_EXPORTED_JSON}\"
-s RESERVED_FUNCTION_POINTERS=10
-s NO_EXIT_RUNTIME=1
)
string(REPLACE ";" " " LIBWABT_LINK_FLAGS_STR "${LIBWABT_LINK_FLAGS}")
set_target_properties(libwabtjs
PROPERTIES
LINK_FLAGS "${LIBWABT_LINK_FLAGS_STR}"
LINK_DEPENDS "${WABT_JS};${EMSCRIPTEN_EXPORTED_JSON}"
)
endif ()