diff --git a/.gitignore b/.gitignore
index 8bcd88d7..ca06dddd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@ Makefile.in
 /INSTALL
 /aclocal.m4
 /autom4te.*
+/build
 /config.cache
 /config.h
 /config.h.in
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..11ad5c13
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright (C) 2022 Yonggang Luo
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+cmake_minimum_required(VERSION 3.16)
+project(libelf
+    LANGUAGES C
+    VERSION 0.187
+)
+
+add_subdirectory(libelf)
+
+include(GNUInstallDirs)
+
+if (LIBELF_INSTALL)
+    # Install the targets
+    install(TARGETS elf
+        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+        PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libelf
+    )
+    set(VERSION ${CMAKE_PROJECT_VERSION})
+    set(prefix ${CMAKE_INSTALL_PREFIX})
+    set(exec_prefix "\${prefix}")
+    set(libdir "\${exec_prefix}/lib")
+    set(includedir "\${prefix}/include/libelf")
+    configure_file(
+        ${CMAKE_CURRENT_SOURCE_DIR}/config/libelf.pc.in
+        ${CMAKE_CURRENT_BINARY_DIR}/libelf.pc
+        @ONLY
+    )
+    install(
+        FILES ${CMAKE_CURRENT_BINARY_DIR}/libelf.pc
+        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
+    )
+endif()
diff --git a/libelf/CMakeLists.txt b/libelf/CMakeLists.txt
new file mode 100644
index 00000000..dc8f9291
--- /dev/null
+++ b/libelf/CMakeLists.txt
@@ -0,0 +1,192 @@
+# Copyright (C) 2022 Yonggang Luo
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+add_library(elf
+    elf_begin.c
+    elf_clone.c
+    elf_cntl.c
+    elf_compress_gnu.c
+    elf_compress.c
+    elf_end.c
+    elf_error.c
+    elf_fill.c
+    elf_flagdata.c
+    elf_flagehdr.c
+    elf_flagelf.c
+    elf_flagphdr.c
+    elf_flagscn.c
+    elf_flagshdr.c
+    elf_getarhdr.c
+    elf_getaroff.c
+    elf_getarsym.c
+    elf_getbase.c
+    elf_getdata_rawchunk.c
+    elf_getdata.c
+    elf_getident.c
+    elf_getphdrnum.c
+    elf_getscn.c
+    elf_getshdrnum.c
+    elf_getshdrstrndx.c
+    elf_gnu_hash.c
+    elf_hash.c
+    elf_kind.c
+    elf_memory.c
+    elf_ndxscn.c
+    elf_newdata.c
+    elf_newscn.c
+    elf_next.c
+    elf_nextscn.c
+    elf_rand.c
+    elf_rawdata.c
+    elf_rawfile.c
+    elf_readall.c
+    elf_scnshndx.c
+    elf_strptr.c
+    elf_update.c
+    elf_version.c
+    elf32_checksum.c
+    elf32_fsize.c
+    elf32_getchdr.c
+    elf32_getehdr.c
+    elf32_getphdr.c
+    elf32_getshdr.c
+    elf32_newehdr.c
+    elf32_newphdr.c
+    elf32_offscn.c
+    elf32_updatefile.c
+    elf32_updatenull.c
+    elf32_xlatetof.c
+    elf32_xlatetom.c
+    elf64_checksum.c
+    elf64_fsize.c
+    elf64_getchdr.c
+    elf64_getehdr.c
+    elf64_getphdr.c
+    elf64_getshdr.c
+    elf64_newehdr.c
+    elf64_newphdr.c
+    elf64_offscn.c
+    elf64_updatefile.c
+    elf64_updatenull.c
+    elf64_xlatetof.c
+    elf64_xlatetom.c
+    gelf_checksum.c
+    gelf_fsize.c
+    gelf_getauxv.c
+    gelf_getchdr.c
+    gelf_getclass.c
+    gelf_getdyn.c
+    gelf_getehdr.c
+    gelf_getlib.c
+    gelf_getmove.c
+    gelf_getnote.c
+    gelf_getphdr.c
+    gelf_getrel.c
+    gelf_getrela.c
+    gelf_getshdr.c
+    gelf_getsym.c
+    gelf_getsyminfo.c
+    gelf_getsymshndx.c
+    gelf_getverdaux.c
+    gelf_getverdef.c
+    gelf_getvernaux.c
+    gelf_getverneed.c
+    gelf_getversym.c
+    gelf_newehdr.c
+    gelf_newphdr.c
+    gelf_offscn.c
+    gelf_update_auxv.c
+    gelf_update_dyn.c
+    gelf_update_ehdr.c
+    gelf_update_lib.c
+    gelf_update_move.c
+    gelf_update_phdr.c
+    gelf_update_rel.c
+    gelf_update_rela.c
+    gelf_update_shdr.c
+    gelf_update_sym.c
+    gelf_update_syminfo.c
+    gelf_update_symshndx.c
+    gelf_update_verdaux.c
+    gelf_update_verdef.c
+    gelf_update_vernaux.c
+    gelf_update_verneed.c
+    gelf_update_versym.c
+    gelf_xlate.c
+    gelf_xlatetof.c
+    gelf_xlatetom.c
+    libelf_crc32.c
+    libelf_next_prime.c
+    nlist.c
+)
+if(WIN32)
+    target_sources(
+        elf PRIVATE
+        ../lib/system_win32.c
+    )
+endif()
+set(ELF_PUBLIC_HEADERS
+    ${CMAKE_CURRENT_SOURCE_DIR}/gelf.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/libelf.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/nlist.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/elf.h
+)
+set_target_properties(
+    elf PROPERTIES PUBLIC_HEADER
+    "${ELF_PUBLIC_HEADERS}"
+)
+target_include_directories(
+    elf PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}/../lib
+    ${CMAKE_CURRENT_SOURCE_DIR}/
+    ${CMAKE_CURRENT_SOURCE_DIR}/config-cmake
+)
+target_compile_definitions(
+    elf PRIVATE
+    -DHAVE_CONFIG_H
+)
+if (MSVC)
+    target_compile_definitions(
+        elf PRIVATE
+        -D_CRT_NONSTDC_NO_DEPRECATE
+        -D_CRT_SECURE_NO_WARNINGS
+        -D_CRT_SECURE_NO_WARNINGS_GLOBALS
+    )
+else()
+    target_compile_definitions(
+        elf PRIVATE
+        -D_FILE_OFFSET_BITS=64
+    )
+endif()
+set_property(TARGET elf PROPERTY C_STANDARD 11)
+
+if (MSVC)
+  # Enable find libz.a with msvc
+  set(CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
+  set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
+endif()
+find_package(ZLIB REQUIRED)
+target_link_libraries(elf ZLIB::ZLIB)
+
+find_package(Intl)
+if (TARGET Intl::Intl)
+    target_link_libraries(elf Intl::Intl)
+else()
+    target_compile_definitions(
+        elf PRIVATE
+        -DNOT_HAVE_LIBINTL
+    )
+endif()
diff --git a/libelf/config-cmake/config.h b/libelf/config-cmake/config.h
new file mode 100644
index 00000000..25f1da57
--- /dev/null
+++ b/libelf/config-cmake/config.h
@@ -0,0 +1,27 @@
+#ifndef _CONFIG_H_
+#define _GNU_SOURCE
+#include "eu-config.h"
+
+#if defined(_WIN32)
+#define HAVE_DECL_MEMPCPY 0
+#define HAVE_DECL_MEMRCHR 0
+#define HAVE_DECL_POWEROF2 0
+#define HAVE_DECL_MMAP 0
+#else
+#define HAVE_DECL_MEMPCPY 1
+#define HAVE_DECL_MEMRCHR 1
+#define HAVE_DECL_POWEROF2 1
+#define HAVE_DECL_MMAP 1
+#endif
+#define HAVE_DECL_RAWMEMCHR 0
+#define HAVE_DECL_REALLOCARRAY 1
+#define HAVE_VISIBILITY 1
+
+#undef HAVE_GCC_STRUCT
+#undef USE_LOCKS
+
+#if !defined(_MSC_VER)
+#define HAVE_ERROR_H
+#endif
+
+#endif /* _CONFIG_H_ */
\ No newline at end of file
