diff --git a/cmake/modules/NativeExecutable.cmake b/cmake/modules/NativeExecutable.cmake
new file mode 100644
index 000000000..6f1f6c89a
--- /dev/null
+++ b/cmake/modules/NativeExecutable.cmake
@@ -0,0 +1,49 @@
+# Allow to easily build native executable.
+# Useful for cross compilation.
+
+# If we are cross compiling, create a directory for native build.
+set(NATIVE_BUILD_DIR "${CMAKE_BINARY_DIR}/native" CACHE PATH "Path to the native build directory")
+set(NATIVE_BINARY_DIR "${NATIVE_BUILD_DIR}/bin" CACHE PATH "Path to the native binary directory")
+set(NATIVE_BUILD_TARGET "${NATIVE_BUILD_DIR}/CMakeCache.txt")
+
+if(CMAKE_CROSSCOMPILING AND NOT TARGET native-cmake-build)
+	find_program(NINJA "ninja")
+
+	file(MAKE_DIRECTORY ${NATIVE_BUILD_DIR})
+	add_custom_command(
+		OUTPUT ${NATIVE_BUILD_TARGET}
+		COMMAND ${CMAKE_COMMAND}
+			-GNinja
+			"${CMAKE_SOURCE_DIR}"
+			-DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${NATIVE_BINARY_DIR}
+		WORKING_DIRECTORY ${NATIVE_BUILD_DIR}
+		VERBATIM USES_TERMINAL
+	)
+
+	add_custom_target(native-cmake-build DEPENDS ${NATIVE_BUILD_TARGET})
+endif()
+
+macro(add_native_executable NAME)
+	if(CMAKE_CROSSCOMPILING)
+		set(NATIVE_BINARY "${NATIVE_BINARY_DIR}/${NAME}")
+		add_custom_target("build-native-${NAME}"
+			COMMAND ${NINJA} ${NAME}
+			DEPENDS ${NATIVE_BUILD_TARGET}
+			BYPRODUCTS ${NATIVE_BINARY}
+			WORKING_DIRECTORY ${NATIVE_BUILD_DIR}
+			VERBATIM USES_TERMINAL
+		)
+
+		add_executable(${NAME} IMPORTED)
+		add_dependencies(${NAME} "build-native-${NAME}")
+		set_property(TARGET ${NAME} PROPERTY IMPORTED_LOCATION ${NATIVE_BINARY})
+	else()
+		add_executable(${NAME} EXCLUDE_FROM_ALL ${ARGN})
+	endif(CMAKE_CROSSCOMPILING)
+endmacro(add_native_executable)
+
+function(native_target_include_directories)
+	if(NOT CMAKE_CROSSCOMPILING)
+		target_include_directories(${ARGN})
+	endif(NOT CMAKE_CROSSCOMPILING)
+endfunction(native_target_include_directories)
diff --git a/src/univalue/CMakeLists.txt b/src/univalue/CMakeLists.txt
index 8a048cb90..0888cafc3 100644
--- a/src/univalue/CMakeLists.txt
+++ b/src/univalue/CMakeLists.txt
@@ -1,59 +1,54 @@
 # Copyright (c) 2017 The Bitcoin developers
 
 cmake_minimum_required(VERSION 3.1)
 project(univalue)
 
 option(UNIVALUE_BUILD_TESTS "Build univalue's unit tests" ON)
 
 # TODO: Version info
 add_library(univalue
 	lib/univalue.cpp
 	lib/univalue_get.cpp
 	lib/univalue_read.cpp
 	lib/univalue_write.cpp
 )
 
 target_include_directories(univalue
 	PUBLIC
 		include
 	PRIVATE
 		lib
 )
 
 if(UNIVALUE_BUILD_TESTS)
 	include(TestSuite)
 	create_test_suite(univalue)
 
 	function(create_univalue_test NAME FILES)
 		add_test_to_suite(univalue ${NAME} ${FILES})
 		target_link_libraries(${NAME} univalue)
 	endfunction()
 
 	create_univalue_test(unitester_test test/unitester.cpp)
 	target_compile_definitions(unitester_test
 		PUBLIC JSON_TEST_SRC="${PROJECT_SOURCE_DIR}/test"
 	)
 
 	create_univalue_test(no_nul_test test/no_nul.cpp)
 	create_univalue_test(object_test test/object.cpp)
 
 	# test_json is not meant to run in an automated test suite.
 	add_executable(json_test EXCLUDE_FROM_ALL test/test_json.cpp)
 	target_link_libraries(json_test univalue)
 	add_dependencies(check-univalue json_test)
 endif(UNIVALUE_BUILD_TESTS)
 
 # Generate lib/univalue_escapes.h
-add_executable(univalue_gen gen/gen.cpp)
-target_include_directories(univalue_gen PUBLIC include)
-
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
-add_custom_command(
-	OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib/univalue_escapes.h
-	COMMAND univalue_gen > ${CMAKE_CURRENT_BINARY_DIR}/lib/univalue_escapes.h
-	DEPENDS univalue_gen ${CMAKE_CURRENT_SOURCE_DIR}/lib/univalue_escapes.h
-)
+include(NativeExecutable)
+add_native_executable(univalue_gen gen/gen.cpp)
+native_target_include_directories(univalue_gen PUBLIC include)
+
+# Custom target to regenerate univalue_escapes.h
 add_custom_target(generate_univalue_escapes_h
-	DEPENDS
-		${CMAKE_CURRENT_BINARY_DIR}/lib/univalue_escapes.h
+	COMMAND univalue_gen > ${CMAKE_CURRENT_SOURCE_DIR}/lib/univalue_escapes.h
 )