diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3ec359f2c7278b2a962838ce986fe6e86afcc5c1
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,242 @@
+# ngtcp2
+#
+# Copyright (c) 2016 ngtcp2 contributors
+# Copyright (c) 2012 nghttp2 contributors
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+cmake_minimum_required(VERSION 3.1)
+# XXX using 0.1.90 instead of 0.1.0-DEV
+project(nghttp2 VERSION 0.1.90)
+
+# See versioning rule:
+#  http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+set(LT_CURRENT  0)
+set(LT_REVISION 0)
+set(LT_AGE      0)
+
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+include(Version)
+
+math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}")
+set(LT_VERSION "${LT_SOVERSION}.${LT_AGE}.${LT_REVISION}")
+set(PACKAGE_VERSION     "${PROJECT_VERSION}")
+HexVersion(PACKAGE_VERSION_NUM ${PROJECT_VERSION_MAJOR} ${PROJECT_VERSION_MINOR} ${PROJECT_VERSION_PATCH})
+
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the build type" FORCE)
+
+  # Include "None" as option to disable any additional (optimization) flags,
+  # relying on just CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (which are empty by
+  # default). These strings are presented in cmake-gui.
+  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+    "None" "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
+endif()
+
+include(GNUInstallDirs)
+
+include(CMakeOptions.txt)
+
+# Do not disable assertions based on CMAKE_BUILD_TYPE.
+foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo")
+  foreach(_lang C CXX)
+    string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var)
+    string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" "" ${_var} "${${_var}}")
+  endforeach()
+endforeach()
+
+
+find_package(OpenSSL 1.1.1)
+find_package(Libev 4.11)
+find_package(CUnit 2.1)
+enable_testing()
+set(HAVE_CUNIT      ${CUNIT_FOUND})
+if(HAVE_CUNIT)
+  add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
+endif()
+
+# openssl (for examples)
+set(HAVE_OPENSSL    ${OPENSSL_FOUND})
+if(OPENSSL_FOUND)
+  set(OPENSSL_INCLUDE_DIRS  ${OPENSSL_INCLUDE_DIR})
+else()
+  set(OPENSSL_INCLUDE_DIRS  "")
+  set(OPENSSL_LIBRARIES     "")
+endif()
+# libev (for examples)
+set(HAVE_LIBEV      ${LIBEV_FOUND})
+
+# Checks for header files.
+include(CheckIncludeFile)
+check_include_file("arpa/inet.h"   HAVE_ARPA_INET_H)
+check_include_file("stddef.h"      HAVE_STDDEF_H)
+check_include_file("stdint.h"      HAVE_STDINT_H)
+check_include_file("stdlib.h"      HAVE_STDLIB_H)
+check_include_file("string.h"      HAVE_STRING_H)
+check_include_file("unistd.h"      HAVE_UNISTD_H)
+
+include(CheckTypeSize)
+# Checks for typedefs, structures, and compiler characteristics.
+# AC_TYPE_SIZE_T
+check_type_size("ssize_t" SIZEOF_SSIZE_T)
+if(SIZEOF_SSIZE_T STREQUAL "")
+  # ssize_t is a signed type in POSIX storing at least -1.
+  # Set it to "int" to match the behavior of AC_TYPE_SSIZE_T (autotools).
+  set(ssize_t int)
+endif()
+
+include(ExtractValidFlags)
+set(WARNCFLAGS)
+set(WARNCXXFLAGS)
+if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
+  if(ENABLE_WERROR)
+    set(WARNCFLAGS    /WX)
+    set(WARNCXXFLAGS  /WX)
+  endif()
+else()
+  if(ENABLE_WERROR)
+    extract_valid_c_flags(WARNCFLAGS    -Werror)
+    extract_valid_c_flags(WARNCXXFLAGS  -Werror)
+  endif()
+
+  # For C compiler
+  extract_valid_c_flags(WARNCFLAGS
+    -Wall
+    -Wextra
+    -Wmissing-prototypes
+    -Wstrict-prototypes
+    -Wmissing-declarations
+    -Wpointer-arith
+    -Wdeclaration-after-statement
+    -Wformat-security
+    -Wwrite-strings
+    -Wshadow
+    -Winline
+    -Wnested-externs
+    -Wfloat-equal
+    -Wundef
+    -Wendif-labels
+    -Wempty-body
+    -Wcast-align
+    -Wclobbered
+    -Wvla
+    -Wpragmas
+    -Wunreachable-code
+    -Waddress
+    -Wattributes
+    -Wdiv-by-zero
+    -Wshorten-64-to-32
+
+    -Wconversion
+    -Wextended-offsetof
+    -Wformat-nonliteral
+    -Wlanguage-extension-token
+    -Wmissing-field-initializers
+    -Wmissing-noreturn
+    -Wmissing-variable-declarations
+    # Not used because we cannot change public structs
+    # -Wpadded
+    -Wsign-conversion
+    # Not used because this basically disallows default case
+    # -Wswitch-enum
+    -Wunreachable-code-break
+    -Wunused-macros
+    -Wunused-parameter
+    -Wredundant-decls
+    # Only work with Clang for the moment
+    -Wheader-guard
+    -Wsometimes-uninitialized
+
+    # This is required because we pass format string as "const char*.
+    -Wno-format-nonliteral
+  )
+
+  extract_valid_cxx_flags(WARNCXXFLAGS
+    # For C++ compiler
+    -Wall
+    -Wformat-security
+    -Wsometimes-uninitialized
+  )
+endif()
+
+if(ENABLE_DEBUG)
+  set(DEBUGBUILD 1)
+endif()
+
+add_definitions(-DHAVE_CONFIG_H)
+configure_file(cmakeconfig.h.in config.h)
+# autotools-compatible names
+# Sphinx expects relative paths in the .rst files. Use the fact that the files
+# below are all one directory level deep.
+file(RELATIVE_PATH top_srcdir   "${CMAKE_CURRENT_BINARY_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}")
+file(RELATIVE_PATH top_builddir "${CMAKE_CURRENT_BINARY_DIR}/dir" "${CMAKE_CURRENT_BINARY_DIR}")
+set(abs_top_srcdir  "${CMAKE_CURRENT_SOURCE_DIR}")
+set(abs_top_builddir "${CMAKE_CURRENT_BINARY_DIR}")
+# libngtcp2.pc (pkg-config file)
+set(prefix          "${CMAKE_INSTALL_PREFIX}")
+set(exec_prefix     "${CMAKE_INSTALL_PREFIX}")
+set(libdir          "${CMAKE_INSTALL_FULL_LIBDIR}")
+set(includedir      "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
+set(VERSION         "${PACKAGE_VERSION}")
+# For init scripts and systemd service file (in contrib/)
+set(bindir          "${CMAKE_INSTALL_FULL_BINDIR}")
+set(sbindir         "${CMAKE_INSTALL_FULL_SBINDIR}")
+foreach(name
+  lib/libngtcp2.pc
+  lib/includes/ngtcp2/version.h
+)
+  configure_file("${name}.in" "${name}" @ONLY)
+endforeach()
+
+include_directories(
+  "${CMAKE_CURRENT_BINARY_DIR}" # for config.h
+)
+# For use in src/CMakeLists.txt
+set(PKGDATADIR "${CMAKE_INSTALL_FULL_DATADIR}/${CMAKE_PROJECT_NAME}")
+
+install(FILES README.rst DESTINATION "${CMAKE_INSTALL_DOCDIR}")
+
+add_subdirectory(lib)
+add_subdirectory(tests)
+add_subdirectory(third-party)
+add_subdirectory(examples)
+
+
+string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type)
+message(STATUS "summary of build options:
+
+    Package version: ${VERSION}
+    Library version: ${LT_CURRENT}:${LT_REVISION}:${LT_AGE}
+    Install prefix:  ${CMAKE_INSTALL_PREFIX}
+    Target system:   ${CMAKE_SYSTEM_NAME}
+    Compiler:
+      Build type:     ${CMAKE_BUILD_TYPE}
+      C compiler:     ${CMAKE_C_COMPILER}
+      CFLAGS:         ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
+      C++ compiler:   ${CMAKE_CXX_COMPILER}
+      CXXFLAGS:       ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
+      WARNCFLAGS:     ${WARNCFLAGS}
+      WARNCXXFLAGS:   ${WARNCXXFLAGS}
+    Test:
+      CUnit:          ${HAVE_CUNIT} (LIBS='${CUNIT_LIBRARIES}')
+    Libs:
+      OpenSSL:        ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
+      Libev:          ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}')
+")
diff --git a/CMakeOptions.txt b/CMakeOptions.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2b06e858793735d2d1058b6a0011deea0c5de405
--- /dev/null
+++ b/CMakeOptions.txt
@@ -0,0 +1,6 @@
+# Features that can be enabled for cmake (see CMakeLists.txt)
+
+option(ENABLE_WERROR    "Make compiler warnings fatal" OFF)
+option(ENABLE_DEBUG     "Turn on debug output")
+
+# vim: ft=cmake:
diff --git a/cmake/ExtractValidFlags.cmake b/cmake/ExtractValidFlags.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..ccd57dc8133b1630a277ee48f43eef296c0d6d0a
--- /dev/null
+++ b/cmake/ExtractValidFlags.cmake
@@ -0,0 +1,31 @@
+# Convenience function that checks the availability of certain
+# C or C++ compiler flags and returns valid ones as a string.
+
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+
+function(extract_valid_c_flags varname)
+  set(valid_flags)
+  foreach(flag IN LISTS ARGN)
+    string(REGEX REPLACE "[^a-zA-Z0-9_]+" "_" flag_var ${flag})
+    set(flag_var "C_FLAG_${flag_var}")
+    check_c_compiler_flag("${flag}" "${flag_var}")
+    if(${flag_var})
+      set(valid_flags "${valid_flags} ${flag}")
+    endif()
+  endforeach()
+  set(${varname} "${valid_flags}" PARENT_SCOPE)
+endfunction()
+
+function(extract_valid_cxx_flags varname)
+  set(valid_flags)
+  foreach(flag IN LISTS ARGN)
+    string(REGEX REPLACE "[^a-zA-Z0-9_]+" "_" flag_var ${flag})
+    set(flag_var "CXX_FLAG_${flag_var}")
+    check_cxx_compiler_flag("${flag}" "${flag_var}")
+    if(${flag_var})
+      set(valid_flags "${valid_flags} ${flag}")
+    endif()
+  endforeach()
+  set(${varname} "${valid_flags}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/FindCUnit.cmake b/cmake/FindCUnit.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..ada87c16531e3d15dc782c4a0f02cde571733a4f
--- /dev/null
+++ b/cmake/FindCUnit.cmake
@@ -0,0 +1,40 @@
+# - Try to find cunit
+# Once done this will define
+#  CUNIT_FOUND        - System has cunit
+#  CUNIT_INCLUDE_DIRS - The cunit include directories
+#  CUNIT_LIBRARIES    - The libraries needed to use cunit
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_CUNIT QUIET cunit)
+
+find_path(CUNIT_INCLUDE_DIR
+  NAMES CUnit/CUnit.h
+  HINTS ${PC_CUNIT_INCLUDE_DIRS}
+)
+find_library(CUNIT_LIBRARY
+  NAMES cunit
+  HINTS ${PC_CUNIT_LIBRARY_DIRS}
+)
+
+if(CUNIT_INCLUDE_DIR)
+  set(_version_regex "^#define[ \t]+CU_VERSION[ \t]+\"([^\"]+)\".*")
+  file(STRINGS "${CUNIT_INCLUDE_DIR}/CUnit/CUnit.h"
+    CUNIT_VERSION REGEX "${_version_regex}")
+  string(REGEX REPLACE "${_version_regex}" "\\1"
+    CUNIT_VERSION "${CUNIT_VERSION}")
+  unset(_version_regex)
+endif()
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set CUNIT_FOUND to TRUE
+# if all listed variables are TRUE and the requested version matches.
+find_package_handle_standard_args(CUnit REQUIRED_VARS
+                                  CUNIT_LIBRARY CUNIT_INCLUDE_DIR
+                                  VERSION_VAR CUNIT_VERSION)
+
+if(CUNIT_FOUND)
+  set(CUNIT_LIBRARIES     ${CUNIT_LIBRARY})
+  set(CUNIT_INCLUDE_DIRS  ${CUNIT_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(CUNIT_INCLUDE_DIR CUNIT_LIBRARY)
diff --git a/cmake/FindLibev.cmake b/cmake/FindLibev.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..71e45082b3bd193eff867958bac599d7d637d5aa
--- /dev/null
+++ b/cmake/FindLibev.cmake
@@ -0,0 +1,38 @@
+# - Try to find libev
+# Once done this will define
+#  LIBEV_FOUND        - System has libev
+#  LIBEV_INCLUDE_DIRS - The libev include directories
+#  LIBEV_LIBRARIES    - The libraries needed to use libev
+
+find_path(LIBEV_INCLUDE_DIR
+  NAMES ev.h
+)
+find_library(LIBEV_LIBRARY
+  NAMES ev
+)
+
+if(LIBEV_INCLUDE_DIR)
+  file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h"
+    LIBEV_VERSION_MAJOR REGEX "^#define[ \t]+EV_VERSION_MAJOR[ \t]+[0-9]+")
+  file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h"
+    LIBEV_VERSION_MINOR REGEX "^#define[ \t]+EV_VERSION_MINOR[ \t]+[0-9]+")
+  string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MAJOR "${LIBEV_VERSION_MAJOR}")
+  string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MINOR "${LIBEV_VERSION_MINOR}")
+  set(LIBEV_VERSION "${LIBEV_VERSION_MAJOR}.${LIBEV_VERSION_MINOR}")
+  unset(LIBEV_VERSION_MINOR)
+  unset(LIBEV_VERSION_MAJOR)
+endif()
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set LIBEV_FOUND to TRUE
+# if all listed variables are TRUE and the requested version matches.
+find_package_handle_standard_args(Libev REQUIRED_VARS
+                                  LIBEV_LIBRARY LIBEV_INCLUDE_DIR
+                                  VERSION_VAR LIBEV_VERSION)
+
+if(LIBEV_FOUND)
+  set(LIBEV_LIBRARIES     ${LIBEV_LIBRARY})
+  set(LIBEV_INCLUDE_DIRS  ${LIBEV_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(LIBEV_INCLUDE_DIR LIBEV_LIBRARY)
diff --git a/cmake/Version.cmake b/cmake/Version.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..8ac4849c9722dab6f82c5d1163dbf402adb7ebc4
--- /dev/null
+++ b/cmake/Version.cmake
@@ -0,0 +1,11 @@
+# Converts a version such as 1.2.255 to 0x0102ff
+function(HexVersion version_hex_var major minor patch)
+  math(EXPR version_dec "${major} * 256 * 256 + ${minor} * 256 + ${patch}")
+  set(version_hex "0x")
+  foreach(i RANGE 5 0 -1)
+    math(EXPR num "(${version_dec} >> (4 * ${i})) & 15")
+    string(SUBSTRING "0123456789abcdef" ${num} 1 num_hex)
+    set(version_hex "${version_hex}${num_hex}")
+  endforeach()
+  set(${version_hex_var} "${version_hex}" PARENT_SCOPE)
+endfunction()
diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..840a8243b48839e4524494fc3d81bdb6b3eabddd
--- /dev/null
+++ b/cmakeconfig.h.in
@@ -0,0 +1,24 @@
+
+/* Define to `int' if <sys/types.h> does not define. */
+#cmakedefine ssize_t @ssize_t@
+
+/* Define to 1 to enable debug output. */
+#cmakedefine DEBUGBUILD 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#cmakedefine HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#cmakedefine HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H 1
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..41f8f7c781e515c7e0c3a2ee6d9ba3503a5a13c8
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,75 @@
+# ngtcp2
+
+# Copyright (c) 2017 ngtcp2 contributors
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if(LIBEV_FOUND AND OPENSSL_FOUND)
+  include_directories(
+    ${CMAKE_SOURCE_DIR}/lib/includes
+    ${CMAKE_BINARY_DIR}/lib/includes
+    ${CMAKE_SOURCE_DIR}/third-party
+
+    ${OPENSSL_INCLUDE_DIRS}
+    ${LIBEV_INCLUDE_DIRS}
+  )
+
+  link_libraries(
+    ngtcp2
+    ${OPENSSL_LIBRARIES}
+    ${LIBEV_LIBRARIES}
+  )
+
+  set(client_SOURCES
+    client.cc
+    debug.cc
+    util.cc
+    shared.cc
+    crypto_openssl.cc
+    crypto.cc
+  )
+
+  set(server_SOURCES
+    server.cc
+    debug.cc
+    util.cc
+    shared.cc
+    crypto_openssl.cc
+    crypto.cc
+    http.cc
+  )
+
+  add_executable(client ${client_SOURCES} $<TARGET_OBJECTS:http-parser>)
+  add_executable(server ${server_SOURCES} $<TARGET_OBJECTS:http-parser>)
+  set_target_properties(client PROPERTIES
+    COMPILE_FLAGS "${WARNCXXFLAGS}"
+    CXX_STANDARD 14
+    CXX_STANDARD_REQUIRED ON
+  )
+  set_target_properties(server PROPERTIES
+    COMPILE_FLAGS "${WARNCXXFLAGS}"
+    CXX_STANDARD 14
+    CXX_STANDARD_REQUIRED ON
+  )
+
+  # TODO prevent client and example servers from being installed?
+else()
+  message(WARNING "Examples are disabled due to lack of good libev or OpenSSL")
+endif()
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..aabe490a98eff9b2959894af7b44edef6e60fe37
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,80 @@
+
+# ngtcp2
+
+# Copyright (c) 2016 ngtcp2
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+add_subdirectory(includes)
+
+include_directories(
+  "${CMAKE_CURRENT_SOURCE_DIR}/includes"
+  "${CMAKE_CURRENT_BINARY_DIR}/includes"
+)
+
+add_definitions(-DBUILDING_NGTCP2)
+
+set(ngtcp2_SOURCES
+  ngtcp2_pkt.c
+  ngtcp2_conv.c
+  ngtcp2_str.c
+  ngtcp2_buf.c
+  ngtcp2_upe.c
+  ngtcp2_conn.c
+  ngtcp2_mem.c
+  ngtcp2_pq.c
+  ngtcp2_map.c
+  ngtcp2_rob.c
+  ngtcp2_ppe.c
+  ngtcp2_crypto.c
+  ngtcp2_err.c
+  ngtcp2_range.c
+  ngtcp2_acktr.c
+  ngtcp2_rtb.c
+  ngtcp2_strm.c
+  ngtcp2_idtr.c
+  ngtcp2_gaptr.c
+  ngtcp2_ringbuf.c
+)
+
+# Public shared library
+add_library(ngtcp2 SHARED ${ngtcp2_SOURCES})
+set_target_properties(ngtcp2 PROPERTIES
+  COMPILE_FLAGS "${WARNCFLAGS}"
+  VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
+  C_VISIBILITY_PRESET hidden
+)
+
+if(HAVE_CUNIT)
+  # Static library (for unittests because of symbol visibility)
+  add_library(ngtcp2_static STATIC ${ngtcp2_SOURCES})
+  set_target_properties(ngtcp2_static PROPERTIES
+    COMPILE_FLAGS "${WARNCFLAGS}"
+    VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
+    ARCHIVE_OUTPUT_NAME ngtcp2
+  )
+  target_compile_definitions(ngtcp2_static PUBLIC "-DNGTCP2_STATICLIB")
+endif()
+
+install(TARGETS ngtcp2
+  DESTINATION "${CMAKE_INSTALL_LIBDIR}")
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libngtcp2.pc"
+  DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5eabf732a1e5cbfadd01825a90484ceb8fcb52ce
--- /dev/null
+++ b/lib/includes/CMakeLists.txt
@@ -0,0 +1,4 @@
+install(FILES
+    ngtcp2/ngtcp2.h
+    "${CMAKE_CURRENT_BINARY_DIR}/ngtcp2/version.h"
+  DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ngtcp2")
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d7e4cdcaa0425a8f3808023af9e527d6b725c413
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,61 @@
+# ngtcp2
+
+# Copyright (c) 2016 ngtcp2 contributors
+# Copyright (c) 2012 nghttp2 contributors
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if(HAVE_CUNIT)
+  include_directories(
+    "${CMAKE_SOURCE_DIR}/lib"
+    "${CMAKE_SOURCE_DIR}/lib/includes"
+    "${CMAKE_BINARY_DIR}/lib/includes"
+    ${CUNIT_INCLUDE_DIRS}
+  )
+
+  set(main_SOURCES
+    main.c
+    ngtcp2_pkt_test.c
+    ngtcp2_upe_test.c
+    ngtcp2_range_test.c
+    ngtcp2_rob_test.c
+    ngtcp2_acktr_test.c
+    ngtcp2_map_test.c
+    ngtcp2_crypto_test.c
+    ngtcp2_rtb_test.c
+    ngtcp2_idtr_test.c
+    ngtcp2_conn_test.c
+    ngtcp2_ringbuf_test.c
+    ngtcp2_test_helper.c
+  )
+
+  add_executable(main EXCLUDE_FROM_ALL
+    ${main_SOURCES}
+  )
+  target_include_directories(main PRIVATE ${CUNIT_INCLUDE_DIRS})
+  # FIXME enable and fix warnings
+  #set_target_properties(main PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}")
+  target_link_libraries(main
+    ngtcp2_static
+    ${CUNIT_LIBRARIES}
+  )
+  add_test(main main)
+  add_dependencies(check main)
+endif()
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1db75c9020d0cb9e8153a9d3c506a3d797327ea9
--- /dev/null
+++ b/third-party/CMakeLists.txt
@@ -0,0 +1,30 @@
+# ngtcp2
+
+# Copyright (c) 2017 ngtcp2 contributors
+# Copyright (c) 2014 nghttp2 contributors
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+set(LIBHTTP_PARSER_SOURCES
+  http-parser/http_parser.c
+)
+add_library(http-parser OBJECT ${LIBHTTP_PARSER_SOURCES})
+set_target_properties(http-parser PROPERTIES
+  POSITION_INDEPENDENT_CODE ON)