diff --git a/CMakeLists.txt b/CMakeLists.txt index 73f10dee..0f633b47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ set(UNICORN_VERSION_MAJOR 2) set(UNICORN_VERSION_MINOR 0) set(UNICORN_VERSION_PATCH 0) +include(bundle_static.cmake) + option(BUILD_SHARED_LIBS "Build shared instead of static library" ${PROJECT_IS_TOP_LEVEL}) option(UNICORN_FUZZ "Enable fuzzing" OFF) option(UNICORN_BUILD_TESTS "Build unicorn tests" ${PROJECT_IS_TOP_LEVEL}) @@ -1279,6 +1281,10 @@ target_include_directories(unicorn PUBLIC include ) +if (NOT BUILD_SHARED_LIBS) + bundle_static_library(unicorn unicorn_static) +endif() + if(UNICORN_INSTALL AND NOT MSVC) include("GNUInstallDirs") file(GLOB UNICORN_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/unicorn/*.h) diff --git a/bundle_static.cmake b/bundle_static.cmake new file mode 100644 index 00000000..c7f06c7d --- /dev/null +++ b/bundle_static.cmake @@ -0,0 +1,93 @@ +# https://cristianadam.eu/20190501/bundling-together-static-libraries-with-cmake/ +function(bundle_static_library tgt_name bundled_tgt_name) + list(APPEND static_libs ${tgt_name}) + + function(_recursively_collect_dependencies input_target) + set(_input_link_libraries LINK_LIBRARIES) + get_target_property(_input_type ${input_target} TYPE) + if (${_input_type} STREQUAL "INTERFACE_LIBRARY") + set(_input_link_libraries INTERFACE_LINK_LIBRARIES) + endif() + get_target_property(public_dependencies ${input_target} ${_input_link_libraries}) + foreach(dependency IN LISTS public_dependencies) + if(TARGET ${dependency}) + get_target_property(alias ${dependency} ALIASED_TARGET) + if (TARGET ${alias}) + set(dependency ${alias}) + endif() + get_target_property(_type ${dependency} TYPE) + if (${_type} STREQUAL "STATIC_LIBRARY") + list(APPEND static_libs ${dependency}) + endif() + + get_property(library_already_added + GLOBAL PROPERTY _${tgt_name}_static_bundle_${dependency}) + if (NOT library_already_added) + set_property(GLOBAL PROPERTY _${tgt_name}_static_bundle_${dependency} ON) + _recursively_collect_dependencies(${dependency}) + endif() + endif() + endforeach() + set(static_libs ${static_libs} PARENT_SCOPE) + endfunction() + + _recursively_collect_dependencies(${tgt_name}) + + list(REMOVE_DUPLICATES static_libs) + + set(bundled_tgt_full_name + ${CMAKE_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${bundled_tgt_name}${CMAKE_STATIC_LIBRARY_SUFFIX}) + + if (UNIX OR APPLE) + file(WRITE ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar.in + "CREATE ${bundled_tgt_full_name}\n" ) + + foreach(tgt IN LISTS static_libs) + file(APPEND ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar.in + "ADDLIB $\n") + endforeach() + + file(APPEND ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar.in "SAVE\n") + file(APPEND ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar.in "END\n") + + file(GENERATE + OUTPUT ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar + INPUT ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar.in) + + set(ar_tool ${CMAKE_AR}) + if (CMAKE_INTERPROCEDURAL_OPTIMIZATION) + set(ar_tool ${CMAKE_CXX_COMPILER_AR}) + endif() + + add_custom_command( + COMMAND ${ar_tool} -M < ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar + OUTPUT ${bundled_tgt_full_name} + COMMENT "Bundling ${bundled_tgt_name}" + VERBATIM) + elseif(MSVC) + find_program(lib_tool lib) + + foreach(tgt IN LISTS static_libs) + list(APPEND static_libs_full_names $) + endforeach() + + add_custom_command( + COMMAND ${lib_tool} /NOLOGO /OUT:${bundled_tgt_full_name} ${static_libs_full_names} + OUTPUT ${bundled_tgt_full_name} + COMMENT "Bundling ${bundled_tgt_name}" + VERBATIM) + else() + message(FATAL_ERROR "Unknown bundle scenario!") + endif() + + add_custom_target(bundling_target ALL DEPENDS ${bundled_tgt_full_name}) + add_dependencies(bundling_target ${tgt_name}) + + add_library(${bundled_tgt_name} STATIC IMPORTED) + set_target_properties(${bundled_tgt_name} + PROPERTIES + IMPORTED_LOCATION ${bundled_tgt_full_name} + INTERFACE_INCLUDE_DIRECTORIES $) + add_dependencies(${bundled_tgt_name} bundling_target) + +endfunction() \ No newline at end of file