diff --git a/upb/cmake/CMakeLists.txt b/upb/cmake/CMakeLists.txt
index 3ebe25780..67a70cf81 100644
--- a/upb/cmake/CMakeLists.txt
+++ b/upb/cmake/CMakeLists.txt
@@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.10...3.24)
 
 project(upb)
 set(CMAKE_C_STANDARD 99)
+set(CMAKE_CXX_STANDARD 11)
 
 # Prevent CMake from setting -rdynamic on Linux (!!).
 SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
@@ -39,7 +40,8 @@ if(UPB_ENABLE_UBSAN)
   set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
 endif()
 
-if(NOT TARGET utf8_range)
+find_package(utf8_range REQUIRED CONFIG)
+if(0)
   if(EXISTS ../../external/utf8_range)
     # utf8_range is already installed
     include_directories(../external/utf8_range)
@@ -60,6 +62,11 @@ if(NOT TARGET utf8_range)
   endif()
 endif()
 
+if (VCPKG_UPB_BUILD_CODEGEN)
+  find_package(absl CONFIG REQUIRED)
+  find_package(protobuf CONFIG REQUIRED)
+endif()
+
 if(APPLE)
   set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup -flat_namespace")
 elseif(UNIX)
@@ -69,17 +76,14 @@ endif()
 enable_testing()
 
 
-add_library(upb INTERFACE
+add_library(upb
     
 )
-target_include_directories(upb INTERFACE
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../cmake>
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINRARY_DIR}>
+target_include_directories(upb PUBLIC
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../..>
 )
 target_link_libraries(upb INTERFACE
-  base
-  mem)
+  )
 
 add_library(generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me INTERFACE
     
@@ -123,4 +127,94 @@ target_link_libraries(generated_reflection_support__only_for_generated_code_do_n
   mini_descriptor
   reflection_internal)
 
+file(GLOB_RECURSE source_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/../" "${CMAKE_CURRENT_SOURCE_DIR}/../*.c")
+list(FILTER source_files EXCLUDE REGEX ".*(_test|upb_so|util|cmake|conformance).*")
+list(TRANSFORM source_files PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/../")
+target_sources(upb PRIVATE ${source_files})
+
+target_include_directories(upb PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../reflection/stage0>)
+target_link_libraries(upb PRIVATE utf8_range::utf8_range)
+
+if (VCPKG_UPB_BUILD_CODEGEN)
+  add_library(common OBJECT
+    ../util/def_to_proto.c
+    ../../upb_generator/common.cc
+    ../../upb_generator/file_layout.cc
+    ../../upb_generator/names.cc
+    ../../upb_generator/stage0/google/protobuf/compiler/plugin.upb.c
+  )
+  target_link_libraries(common PUBLIC 
+    upb
+    absl::flat_hash_map
+  )
+  target_include_directories(common PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../upb_generator/stage0>)
+
+  add_executable(protoc-gen-upbdefs
+    ../../upb_generator/protoc-gen-upbdefs.cc
+  )
+  target_link_libraries(protoc-gen-upbdefs PRIVATE
+    common
+    absl::absl_log
+    absl::strings
+    protobuf::libprotobuf
+    protobuf::libprotoc
+  )
+
+  add_executable(protoc-gen-upb
+    ../../upb_generator/protoc-gen-upb.cc
+  )
+  target_link_libraries(protoc-gen-upb PRIVATE
+    common
+    absl::absl_log
+    absl::strings
+    protobuf::libprotobuf
+    protobuf::libprotoc
+  )
+
+  add_executable(protoc-gen-upb_minitable
+    ../../upb_generator/protoc-gen-upb_minitable.cc
+  )
+  target_link_libraries(protoc-gen-upb_minitable PRIVATE
+    common
+    absl::absl_log
+    absl::strings
+    protobuf::libprotobuf
+    protobuf::libprotoc
+  )
+
+  list(APPEND _upb_codegen_targets protoc-gen-upbdefs protoc-gen-upb protoc-gen-upb_minitable)
+endif()
 
+include(GNUInstallDirs)
+
+target_include_directories(upb PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/reflection/stage0>)
+
+install(EXPORT ${PROJECT_NAME}-targets
+  DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}"
+  NAMESPACE ${PROJECT_NAME}::
+)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" 
+  "include(CMakeFindDependencyMacro)\nfind_dependency(utf8_range)\ninclude(\"\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}-targets.cmake\")")
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}")
+
+install(TARGETS upb ${_upb_codegen_targets} EXPORT ${PROJECT_NAME}-targets
+      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+)
+
+install(FILES 
+  ../upb.hpp
+  ../generated_code_support.h
+  DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}"
+)
+foreach(_dir base collections hash io json lex mem message mini_descriptor mini_table port reflection text wire)
+  install(DIRECTORY "../${_dir}"
+    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}"
+    FILES_MATCHING
+    PATTERN "*.hpp"
+    PATTERN "*.h"
+    PATTERN "*.inc"
+  )
+endforeach()