1# Copyright 2018 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4# the License. You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 9# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10# specific language governing permissions and limitations under the License. 11# This contains a set of functions to make working with different targets a lot easier. The idea is that you can now set 12# properties that define your lib/executable through variables that follow the following naming conventions 13# 14if(INCLUDE_ANDROID_CMAKE) 15 return() 16endif() 17 18set(INCLUDE_ANDROID_CMAKE 1) 19 20# We want to make sure all the cross targets end up in a unique location 21set(ANDROID_CROSS_BUILD_DIRECTORY ${CMAKE_BINARY_DIR}/build/${ANDROID_HOST_TAG}) 22 23# Checks to make sure the TAG is valid. 24function(_check_target_tag TAG) 25 set(VALID_TARGETS 26 windows 27 windows_msvc-x86_64 28 linux-x86_64 29 linux-aarch64 30 darwin-x86_64 31 all 32 Clang) 33 if(NOT (TAG IN_LIST VALID_TARGETS)) 34 message( 35 FATAL_ERROR 36 "The target ${TAG} does not exist, has to be one of: ${VALID_TARGETS}") 37 endif() 38endfunction() 39 40# Cross compiles the given cmake project if needed. 41# 42# EXE the name of the target we are interested in. This is the main build 43# product you want to use. SOURCE the location of the CMakeList.txt describing 44# the project. OUT_PATH Name of the variable that will contain the resulting 45# executable. 46function(android_compile_for_host EXE SOURCE OUT_PATH) 47 if(NOT CROSSCOMPILE) 48 # We can add this project without any translation.. 49 if(NOT TARGET ${EXE}) 50 message(STATUS "Adding ${EXE} as subproject, not cross compiling.") 51 add_subdirectory(${SOURCE} ${EXE}_ext) 52 endif() 53 set(${OUT_PATH} "$<TARGET_FILE:${EXE}>" PARENT_SCOPE) 54 else() 55 include(ExternalProject) 56 57 # If we are cross compiling we will need to build it for our actual OS we 58 # are currently running on. 59 get_filename_component( 60 BUILD_PRODUCT 61 ${ANDROID_CROSS_BUILD_DIRECTORY}/${EXE}_ext_cross/src/${EXE}_ext_cross-build/${EXE} 62 ABSOLUTE) 63 if(NOT TARGET ${EXE}_ext_cross) 64 message(STATUS "Cross compiling ${EXE} for host ${ANDROID_HOST_TAG}") 65 externalproject_add( 66 ${EXE}_ext_cross 67 PREFIX ${ANDROID_CROSS_BUILD_DIRECTORY}/${EXE}_ext_cross 68 DOWNLOAD_COMMAND "" 69 SOURCE_DIR ${SOURCE} 70 CMAKE_ARGS 71 "-DCMAKE_TOOLCHAIN_FILE=${ANDROID_QEMU2_TOP_DIR}/android/build/cmake/toolchain-${ANDROID_HOST_TAG}.cmake" 72 BUILD_BYPRODUCTS ${BUILD_PRODUCT} 73 TEST_BEFORE_INSTALL True 74 INSTALL_COMMAND "") 75 endif() 76 set(${OUT_PATH} ${BUILD_PRODUCT} PARENT_SCOPE) 77 endif() 78endfunction() 79 80# ~~~ 81# Enable the compilation of .asm files using nasm. This will include the nasm project if needed to compile the assembly 82# files. 83# 84# The following parameters are accepted 85# 86# ``TARGET`` The library target to generate. 87# ``INCLUDES`` Optional list of include paths to pass to nasm 88# ``SOURCES`` List of source files to be compiled. 89# 90# For example: 91# android_nasm_compile(TARGET foo_asm INCLUDES /tmp/foo /tmp/more_foo SOURCES /tmp/bar /tmp/z) 92# 93# nasm will be compiled for the HOST platform if needed. 94# ~~~ 95function(android_nasm_compile) 96 _register_target(${ARGN}) 97 # Parse arguments 98 set(options) 99 set(oneValueArgs TARGET) 100 set(multiValueArgs INCLUDES SOURCES) 101 cmake_parse_arguments(android_nasm_compile "${options}" "${oneValueArgs}" 102 "${multiValueArgs}" ${ARGN}) 103 104 # Configure nasm 105 android_compile_for_host( 106 nasm ${ANDROID_QEMU2_TOP_DIR}/android/third_party/nasm nasm_EXECUTABLE) 107 108 # Setup the includes. 109 set(LIBNAME ${android_nasm_compile_TARGET}) 110 set(ASM_INC "") 111 foreach(INCLUDE ${android_nasm_compile_INCLUDES}) 112 set(ASM_INC ${ASM_INC} -I ${INCLUDE}) 113 endforeach() 114 115 # Configure the nasm compile command. 116 foreach(asm ${REGISTERED_SRC}) 117 get_filename_component(asm_base ${asm} NAME_WE) 118 set(DST ${CMAKE_CURRENT_BINARY_DIR}/${asm_base}.o) 119 add_custom_command( 120 OUTPUT ${DST} 121 COMMAND ${nasm_EXECUTABLE} -f ${ANDROID_ASM_TYPE} -o ${DST} ${asm} 122 ${ASM_INC} 123 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 124 VERBATIM 125 DEPENDS ${nasm_EXECUTABLE} ${asm}) 126 list(APPEND ${LIBNAME}_asm_o ${DST}) 127 endforeach() 128 129 # Make the library available 130 add_library(${LIBNAME} ${${LIBNAME}_asm_o}) 131 set_target_properties(${LIBNAME} PROPERTIES LINKER_LANGUAGE CXX) 132endfunction() 133 134# This function is the same as target_compile_definitions 135# (https://cmake.org/cmake/help/v3.5/command/target_compile_definitions.html) 136# The only difference is that the definitions will only be applied if the OS 137# parameter matches the ANDROID_TARGET_TAG or compiler variable. 138function(android_target_compile_definitions TGT OS MODIFIER ITEMS) 139 _check_target_tag(${OS}) 140 if(ANDROID_TARGET_TAG MATCHES "${OS}.*" OR OS STREQUAL "all" 141 OR OS MATCHES "${CMAKE_CXX_COMPILER_ID}") 142 target_compile_definitions(${TGT} ${MODIFIER} ${ITEMS}) 143 foreach(DEF ${ARGN}) 144 target_compile_definitions(${TGT} ${MODIFIER} ${DEF}) 145 endforeach() 146 endif() 147endfunction() 148 149# This function is the same as target_link_libraries 150# (https://cmake.org/cmake/help/v3.5/command/target_link_libraries.html) T he 151# only difference is that the definitions will only be applied if the OS 152# parameter matches the ANDROID_TARGET_TAG or Compiler variable. 153function(android_target_link_libraries TGT OS MODIFIER ITEMS) 154 if(ARGC GREATER "49") 155 message( 156 FATAL_ERROR 157 "Currently cannot link more than 49 dependecies due to some weirdness with calling target_link_libs" 158 ) 159 endif() 160 _check_target_tag(${OS}) 161 if(ANDROID_TARGET_TAG MATCHES "${OS}.*" OR OS STREQUAL "all" 162 OR OS MATCHES "${CMAKE_CXX_COMPILER_ID}") 163 # HACK ATTACK! We cannot properly expand unknown linker args as they are 164 # treated in a magical fashion. Some arguments need to be "grouped" together 165 # somehow (for example optimized;lib) since we cannot resolve this properly 166 # we just pass on the individual arguments.. 167 # cmake-format: off 168 target_link_libraries(${TGT} ${MODIFIER} ${ARGV3} ${ARGV4} ${ARGV5} ${ARGV6} ${ARGV7} ${ARGV8} ${ARGV9} 169 ${ARGV10} ${ARGV11} ${ARGV12} ${ARGV13} ${ARGV14} ${ARGV15} ${ARGV16} ${ARGV17} ${ARGV18} ${ARGV19} 170 ${ARGV20} ${ARGV21} ${ARGV22} ${ARGV23} ${ARGV24} ${ARGV25} ${ARGV26} ${ARGV27} ${ARGV28} ${ARGV29} 171 ${ARGV30} ${ARGV31} ${ARGV32} ${ARGV33} ${ARGV34} ${ARGV35} ${ARGV36} ${ARGV37} ${ARGV38} ${ARGV39} 172 ${ARGV40} ${ARGV41} ${ARGV42} ${ARGV43} ${ARGV44} ${ARGV45} ${ARGV46} ${ARGV47} ${ARGV48} ${ARGV49}) 173 # cmake-format: on 174 endif() 175endfunction() 176 177# This function is the same as target_include_directories 178# (https://cmake.org/cmake/help/v3.5/command/target_include_directories.html) 179# The only difference is that the definitions will only be applied if the OS 180# parameter matches the ANDROID_TARGET_TAG variable. 181function(android_target_include_directories TGT OS MODIFIER ITEMS) 182 _check_target_tag(${OS}) 183 if(ANDROID_TARGET_TAG MATCHES "${OS}.*" OR OS STREQUAL "all" 184 OR OS MATCHES "${CMAKE_CXX_COMPILER_ID}") 185 target_include_directories(${TGT} ${MODIFIER} ${ITEMS}) 186 foreach(DIR ${ARGN}) 187 target_include_directories(${TGT} ${MODIFIER} ${DIR}) 188 endforeach() 189 endif() 190endfunction() 191 192# This function is the same as target_compile_options 193# (https://cmake.org/cmake/help/v3.5/command/target_compile_options.html) The 194# only difference is that the definitions will only be applied if the OS 195# parameter matches the ANDROID_TARGET_TAG variable. 196function(android_target_compile_options TGT OS MODIFIER ITEMS) 197 _check_target_tag(${OS}) 198 if(ANDROID_TARGET_TAG MATCHES "${OS}.*" OR OS STREQUAL "all" 199 OR OS MATCHES "${CMAKE_CXX_COMPILER_ID}") 200 target_compile_options(${TGT} ${MODIFIER} "${ITEMS};${ARGN}") 201 endif() 202endfunction() 203 204# ~~~ 205# Registers the given target, by calculating the source set and setting licensens. 206# 207# ``TARGET`` The library/executable target. For example emulatory-libyuv 208# ``LIBNAME`` Public library name, this is how it is known in the world. For example libyuv. 209# ``SOURCES`` List of source files to be compiled, part of every target. 210# ``LINUX`` List of source files to be compiled if the current target is LINUX_X86_64 211# ``DARWIN`` List of source files to be compiled if the current target is DARWIN_X86_64 212# ``WINDOWS`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 213# ``MSVC`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 214# ``URL`` URL where the source code can be found. 215# ``REPO`` Internal location where the, where the notice can be found. 216# ``LICENSE`` SPDX License identifier. 217# ``NOTICE`` Location where the NOTICE can be found 218# ~~~ 219function(_register_target) 220 set(options NODISTRIBUTE) 221 set(oneValueArgs TARGET LICENSE LIBNAME REPO URL NOTICE) 222 set(multiValueArgs SRC LINUX MSVC WINDOWS DARWIN) 223 cmake_parse_arguments(build "${options}" "${oneValueArgs}" 224 "${multiValueArgs}" ${ARGN}) 225 if(NOT DEFINED build_TARGET) 226 message(FATAL_ERROR "Undefined target for library.") 227 endif() 228 229 set(src ${build_SRC}) 230 if(LINUX AND build_LINUX) 231 list(APPEND src ${build_LINUX}) 232 elseif(DARWIN_X86_64 AND build_DARWIN) 233 list(APPEND src ${build_DARWIN}) 234 elseif(WINDOWS_MSVC_X86_64 AND (build_MSVC OR build_WINDOWS)) 235 list(APPEND src ${build_MSVC} ${build_WINDOWS}) 236 endif() 237 238 set(REGISTERED_SRC ${src} PARENT_SCOPE) 239 if(build_NODISTRIBUTE) 240 return() 241 endif() 242 243 if(NOT DEFINED build_LIBNAME) 244 set(build_LIBNAME ${build_TARGET}) 245 endif() 246 247 if(NOT DEFINED build_LICENSE) 248 message( 249 FATAL_ERROR 250 "You must set a license for ${build_TARGET}, or declare NODISTRIBUTE") 251 endif() 252 253 if(NOT DEFINED build_NOTICE) 254 set(build_URL 255 "https://android.googlesource.com/platform/external/qemu.git/+/refs/heads/emu-master-dev" 256 ) 257 set(build_REPO "INTERNAL") 258 set(build_NOTICE "REPO/LICENSES/LICENSE.APACHE2") 259 endif() 260 261 if(NOT DEFINED build_URL OR NOT DEFINED build_REPO OR NOT DEFINED 262 build_NOTICE) 263 message( 264 FATAL_ERROR 265 "You must set a notice/url/repo for ${build_TARGET}, or declare NODISTRIBUTE" 266 ) 267 endif() 268 if(DEFINED build_NOTICE AND NOT ${build_NODISTRIBUTE}) 269 string(REPLACE "REPO" "${build_URL}" REMOTE_LICENSE ${build_NOTICE}) 270 string(REPLACE "REPO" "${build_REPO}" LOCAL_LICENSE ${build_NOTICE}) 271 android_license( 272 TARGET ${build_TARGET} URL ${build_URL} LIBNAME ${build_LIBNAME} 273 SPDX ${build_LICENSE} LICENSE ${REMOTE_LICENSE} LOCAL ${LOCAL_LICENSE}) 274 endif() 275endfunction() 276 277# ~~~ 278# Registers the given library, by calculating the source set and setting licensens. 279# 280# ``SHARED`` Option indicating that this is a shared library. 281# ``TARGET`` The library/executable target. For example emulatory-libyuv 282# ``LIBNAME`` Public library name, this is how it is known in the world. For example libyuv. 283# ``SOURCES`` List of source files to be compiled, part of every target. 284# ``LINUX`` List of source files to be compiled if the current target is LINUX_X86_64 285# ``DARWIN`` List of source files to be compiled if the current target is DARWIN_X86_64 286# ``WINDOWS`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 287# ``MSVC`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 288# ``URL`` URL where the source code can be found. 289# ``REPO`` Internal location where the, where the notice can be found. 290# ``LICENSE`` SPDX License identifier. 291# ``NOTICE`` Location where the NOTICE can be found 292# ~~~ 293function(android_add_library) 294 _register_target(${ARGN}) 295 set(options SHARED) 296 set(oneValueArgs TARGET) 297 set(multiValueArgs "") 298 cmake_parse_arguments(build "${options}" "${oneValueArgs}" 299 "${multiValueArgs}" ${ARGN}) 300 if(${build_SHARED}) 301 add_library(${build_TARGET} SHARED ${REGISTERED_SRC}) 302 else() 303 add_library(${build_TARGET} ${REGISTERED_SRC}) 304 endif() 305 306 if(WINDOWS_MSVC_X86_64 AND NOT ${build_TARGET} STREQUAL "msvc-posix-compat") 307 target_link_libraries(${build_TARGET} PRIVATE msvc-posix-compat) 308 endif() 309 android_clang_tidy(${build_TARGET}) 310 # Clang on mac os does not get properly recognized by cmake 311 if (NOT DARWIN_X86_64) 312 target_compile_features(${build_TARGET} PRIVATE cxx_std_17) 313 endif() 314 315 if(${build_SHARED}) 316 # We don't want cmake to binplace the shared libraries into the bin 317 # directory As this can make them show up in unexpected places! 318 if(ANDROID_TARGET_TAG MATCHES "windows.*") 319 set_target_properties( 320 ${build_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY 321 ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) 322 endif() 323 if(CROSSCOMPILE AND WINDOWS_MSVC_X86_64) 324 # For windows-msvc build (on linux), this generates a dll and a lib 325 # (import library) file. The files are being placed at 326 # ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} which is correct for the dll, but the 327 # lib file needs to be in the ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} or we 328 # can't link to it. Most windows compilers, including clang, don't allow 329 # you to directly link to a dll (unlike mingw), and instead, need to link 330 # to it's import library. 331 # 332 # Another headache: it seems we attach a prefix to some of our shared 333 # libraries, which make cmake unable to locate the import library later on 334 # to whoever tries to link to it (e.g. OpenglRender -> lib64OpenglRender), 335 # as it will look for an import library by <target_library_name>.lib. We 336 # just symlink things to make it work. 337 add_custom_command( 338 TARGET ${build_TARGET} 339 POST_BUILD 340 COMMAND 341 ${CMAKE_COMMAND} -E create_symlink 342 $<TARGET_FILE_DIR:${build_TARGET}>/${CMAKE_SHARED_LIBRARY_PREFIX}$<TARGET_LINKER_FILE_NAME:${build_TARGET}> 343 ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/$<TARGET_LINKER_FILE_NAME:${build_TARGET}> 344 COMMENT 345 "ln -sf $<TARGET_FILE_DIR:${build_TARGET}>/${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/$<TARGET_LINKER_FILE_NAME:${build_TARGET}> ${CMAKE_SHARED_LIBRARY_PREFIX}$<TARGET_LINKER_FILE_NAME:${build_TARGET}>" 346 ) 347 endif() 348 endif() 349endfunction() 350 351# Discovers all the targets that are registered by this subdirectory. 352# 353# result: The variable containing all the targets defined by this project 354# subdir: The directory of interest 355function(android_discover_targets result subdir) 356 if(CMAKE_VERSION VERSION_LESS "3.7.0") 357 message( 358 FATAL_ERROR 359 "This function cannot be used by older cmake versions (${CMAKE_VERSION}<3.7.0)" 360 ) 361 endif() 362 get_directory_property(subdirs DIRECTORY "${subdir}" SUBDIRECTORIES) 363 foreach(subdir IN LISTS subdirs) 364 android_discover_targets(${result} "${subdir}") 365 endforeach() 366 get_property(targets_in_dir DIRECTORY "${subdir}" 367 PROPERTY BUILDSYSTEM_TARGETS) 368 set(${result} ${${result}} ${targets_in_dir} PARENT_SCOPE) 369endfunction() 370 371# Adds an external project, transforming all external "executables" to include 372# the runtime properties. On linux for example this will set the rpath to find 373# libc++ 374# 375# NOTE: This function requires CMake version > 3.7 376function(android_add_subdirectory external_directory name) 377 get_filename_component(abs_dir ${external_directory} ABSOLUTE) 378 add_subdirectory(${abs_dir} ${name}) 379 android_discover_targets(targets ${abs_dir}) 380 foreach(target IN LISTS targets) 381 get_target_property(tgt_type ${target} TYPE) 382 if(tgt_type STREQUAL "EXECUTABLE") 383 android_target_properties(${target} all "${RUNTIME_OS_PROPERTIES}") 384 endif() 385 endforeach() 386endfunction() 387 388function(android_clang_tidy name) 389 if(${name} IN_LIST OPTION_CLANG_TIDY) 390 message(STATUS "Tidying ${name}") 391 if(OPTION_CLANG_TIDY_FIX) 392 message(STATUS " ===> Applying fixes to ${name}") 393 endif() 394 set_target_properties(${name} PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") 395 endif() 396endfunction() 397 398# ~~~ 399# Registers the given library as an interface by calculating the source set and setting licensens. 400# An INTERFACE library target does not directly create build output, though it may have properties 401# set on it and it may be installed, exported and imported. 402# 403# ``TARGET`` The library/executable target. For example emulatory-libyuv 404# ``LIBNAME`` Public library name, this is how it is known in the world. For example libyuv. 405# ``URL`` URL where the source code can be found. 406# ``REPO`` Internal location where the, where the notice can be found. 407# ``LICENSE`` SPDX License identifier. 408# ``NOTICE`` Location where the NOTICE can be found 409# ~~~ 410function(android_add_interface) 411 _register_target(${ARGN}) 412 set(options "") 413 set(oneValueArgs TARGET) 414 set(multiValueArgs "") 415 cmake_parse_arguments(build "${options}" "${oneValueArgs}" 416 "${multiValueArgs}" ${ARGN}) 417 add_library(${build_TARGET} INTERFACE) 418endfunction() 419 420define_property( 421 GLOBAL PROPERTY LICENSES_LST BRIEF_DOCS "Global list of license definitions" 422 FULL_DOCS "Global list of license definitions") 423define_property( 424 GLOBAL PROPERTY INSTALL_TARGETS_LST 425 BRIEF_DOCS "GLobal list of targets that are installed." 426 FULL_DOCS "GLobal list of targets that are installed.") 427set_property(GLOBAL PROPERTY LICENSES_LST " ") 428set_property(GLOBAL PROPERTY INSTALL_TARGETS_LST " ") 429 430# ~~~ 431# ! android_license: Registers the given license, ands adds it to LICENSES_LST for post processing ! 432# 433# ``LIBNAME`` The name of the library, this is how it is usually known in the world. 434# for example: libpng 435# ``URL`` The location where the source code for this library can be found. 436# ``TARGET`` List of targets that are part of the named library. For example crypto;ssl 437# ``SPDX`` The spdx license identifier. (See https://spdx.org/) 438# ``LOCAL`` Path to the NOTICE/LICENSE file. 439# ``LICENSE`` Url to the actual license file. 440# ~~ 441function(android_license) 442 # Parse arguments 443 set(options) 444 set(oneValueArgs LIBNAME URL SPDX LICENSE LOCAL) 445 set(multiValueArgs TARGET) 446 cmake_parse_arguments(args "${options}" "${oneValueArgs}" "${multiValueArgs}" 447 ${ARGN}) 448 string(REPLACE "//" "/" URL "${args_URL}") 449 string(REPLACE ":/" "://" URL "${URL}") 450 string(REPLACE "//" "/" LICENSE "${args_LICENSE}") 451 string(REPLACE ":/" "://" LICENSE "${LICENSE}") 452 set_property( 453 GLOBAL APPEND 454 PROPERTY 455 LICENSES_LST 456 "${args_TARGET}|${args_LIBNAME}|${URL}|${args_SPDX}|${LICENSE}|${args_LOCAL}\n" 457 ) 458endfunction() 459 460# ~~~ 461# Finalize all licenses: 462# 463# 1. Writes out all license related information to a file. 464# 2. Invokes the python license validator. 465# ~~~ 466function(finalize_all_licenses) 467 android_discover_targets(ALL_TARGETS ${ANDROID_QEMU2_TOP_DIR}) 468 get_property(LICENSES GLOBAL PROPERTY LICENSES_LST) 469 get_property(TARGETS GLOBAL PROPERTY INSTALL_TARGETS_LST) 470 file(REMOVE ${CMAKE_BINARY_DIR}/TARGET_DEPS.LST) 471 file(WRITE ${CMAKE_BINARY_DIR}/LICENSES.LST "${LICENSES}") 472 file(WRITE ${CMAKE_BINARY_DIR}/INSTALL_TARGETS.LST "${TARGETS}") 473 foreach(tgt ${ALL_TARGETS}) 474 get_target_property(target_type "${tgt}" TYPE) 475 set(DEPS "") 476 if(NOT target_type STREQUAL "INTERFACE_LIBRARY") 477 get_target_property(DEPS ${tgt} LINK_LIBRARIES) 478 endif() 479 file(APPEND ${CMAKE_BINARY_DIR}/TARGET_DEPS.LST 480 ";${tgt}|${target_type}|${DEPS}\n") 481 endforeach() 482 483 execute_process( 484 COMMAND "python" "android/build/python/aemu/licensing.py" 485 "${PROJECT_BINARY_DIR}" WORKING_DIRECTORY ${ANDROID_QEMU2_TOP_DIR} 486 RESULT_VARIABLE LICENSE_RES OUTPUT_VARIABLE STD_OUT ERROR_VARIABLE STD_ERR) 487 if(NOT "${LICENSE_RES}" STREQUAL "0") 488 message( 489 FATAL_ERROR 490 "Unable to validate licenses, out: ${STD_OUT}, err: ${STD_ERR}") 491 endif() 492endfunction() 493 494# Creates the dependency 495function(android_install_license tgt targetname) 496 set_property(GLOBAL APPEND PROPERTY INSTALL_TARGETS_LST 497 "${tgt}|${targetname}\n") 498endfunction() 499 500function(android_add_default_test_properties name) 501 # Configure the test to run with asan.. 502 file(READ "${ANDROID_QEMU2_TOP_DIR}/android/asan_overrides" ASAN_OVERRIDES) 503 set_property(TEST ${name} PROPERTY ENVIRONMENT 504 "ASAN_OPTIONS=${ASAN_OVERRIDES}") 505 set_property( 506 TEST ${name} APPEND 507 PROPERTY ENVIRONMENT 508 "LLVM_PROFILE_FILE=$<TARGET_FILE_NAME:${name}>.profraw") 509 set_property( 510 TEST ${name} APPEND 511 PROPERTY ENVIRONMENT "ASAN_SYMBOLIZER_PATH=${ANDROID_LLVM_SYMBOLIZER}") 512 set_property(TEST ${name} PROPERTY TIMEOUT 600) 513 514 if(WINDOWS_MSVC_X86_64) 515 # Let's include the .dll path for our test runner 516 string( 517 REPLACE 518 "/" 519 "\\" 520 WIN_PATH 521 "${CMAKE_LIBRARY_OUTPUT_DIRECTORY};${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/gles_swiftshader;${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/qt/lib;$ENV{PATH}" 522 ) 523 string( 524 REPLACE 525 ";" 526 "\;" 527 WIN_PATH 528 "${WIN_PATH}" 529 ) 530 set_property(TEST ${name} APPEND PROPERTY ENVIRONMENT "PATH=${WIN_PATH}") 531 endif() 532endfunction() 533 534# ~~~ 535# Adds a test target. It will create and register the test with the given name. 536# Test targets are marked as NODISTRIBUTE and hence cannot be installed 537# 538# ``TARGET`` The library/executable target. For example emulatory-libyuv 539# ``SOURCES`` List of source files to be compiled, part of every target. 540# ``LINUX`` List of source files to be compiled if the current target is LINUX_X86_64 541# ``DARWIN`` List of source files to be compiled if the current target is DARWIN_X86_64 542# ``WINDOWS`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 543# ``MSVC`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 544# ~~~ 545function(android_add_test) 546 android_add_executable(${ARGN} NODISTRIBUTE) 547 548 set(options "") 549 set(oneValueArgs TARGET) 550 set(multiValueArgs "") 551 cmake_parse_arguments(build "${options}" "${oneValueArgs}" 552 "${multiValueArgs}" ${ARGN}) 553 554 add_test( 555 NAME ${build_TARGET} 556 COMMAND 557 $<TARGET_FILE:${build_TARGET}> 558 --gtest_output=xml:$<TARGET_FILE_NAME:${build_TARGET}>.xml 559 --gtest_catch_exceptions=0 560 WORKING_DIRECTORY $<TARGET_FILE_DIR:${build_TARGET}>) 561 562 android_install_as_debug_info(${build_TARGET}) 563 # Let's not optimize our tests. 564 target_compile_options(${build_TARGET} PRIVATE -O0) 565 566 android_add_default_test_properties(${build_TARGET}) 567endfunction() 568 569# Installs the given target into ${DBG_INFO}/tests/ directory.. This is mainly 570# there so we can preserve it as part of our automated builds. 571function(android_install_as_debug_info name) 572 if(NOT DEFINED DBG_INFO) 573 # Ignore when cross-compiling withouth dbg_info available. 574 return() 575 endif() 576 577 # TODO(jansene): Would be nice if we could make this part of install. 578 add_custom_command( 579 TARGET ${name} POST_BUILD 580 COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${name}> 581 ${DBG_INFO}/tests/$<TARGET_FILE_NAME:${name}>) 582endfunction() 583 584# ~~~ 585# Adds the given executable, by calculating the source set and registering the license 586# 587# ``SHARED`` Option indicating that this is a shared library. 588# ``NODISTRIBUTE`` Option indicating that we will not distribute this. 589# ``INSTALL`` Location where this executable should be installed if needed. 590# ``TARGET`` The library/executable target. For example emulatory-libyuv 591# ``LIBNAME`` Public library name, this is how it is known in the world. For example libyuv. 592# ``SOURCES`` List of source files to be compiled, part of every target. 593# ``LINUX`` List of source files to be compiled if the current target is LINUX_X86_64 594# ``DARWIN`` List of source files to be compiled if the current target is DARWIN_X86_64 595# ``WINDOWS`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 596# ``MSVC`` List of source files to be compiled if the current target is WINDOWS_MSVC_X86_64 597# ``URL`` URL where the source code can be found. 598# ``REPO`` Internal location where the notice can be found. 599# ``LICENSE`` SPDX License identifier. 600# ``NOTICE`` Location where the NOTICE can be found relative to the source URL. Should be written 601# as REPO/path/to/license. 602# ~~~ 603function(android_add_executable) 604 _register_target(${ARGN}) 605 set(options "") 606 set(oneValueArgs TARGET INSTALL) 607 set(multiValueArgs "") 608 cmake_parse_arguments(build "${options}" "${oneValueArgs}" 609 "${multiValueArgs}" ${ARGN}) 610 611 add_executable(${build_TARGET} ${REGISTERED_SRC}) 612 # Clang on mac os does not get properly recognized by cmake 613 if (NOT DARWIN_X86_64) 614 target_compile_features(${build_TARGET} PRIVATE cxx_std_17) 615 endif() 616 617 if(WINDOWS_MSVC_X86_64) 618 target_link_libraries(${build_TARGET} PRIVATE msvc-posix-compat) 619 endif() 620 621 android_clang_tidy(${build_TARGET}) 622 android_target_dependency(${build_TARGET} all RUNTIME_OS_DEPENDENCIES) 623 android_target_properties(${build_TARGET} all "${RUNTIME_OS_PROPERTIES}") 624 625 if(ANDROID_CODE_COVERAGE) 626 # TODO Clean out existing .gcda files. 627 endif() 628 629 if(DEFINED build_INSTALL) 630 android_install_exe(${build_TARGET} ${build_INSTALL}) 631 endif() 632endfunction() 633 634# Adds a protobuf library with the given name. It will export all the needed 635# headers, and libraries You can take a dependency on this by adding: 636# target_link_libraries(my_target ${name}) for your target. The generated 637# library will not use execeptions. Protobuf targets will be licensed under the 638# Apache-2.0 license. 639# 640# name: The name of the generated library. You can take a dependency on this 641# with setting target_linke_libraries(my_target ${name}) 642# 643# protofiles: The set of protofiles to be included. 644function(android_add_protobuf name protofiles) 645 protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${protofiles}) 646 android_add_library(TARGET ${name} LICENSE Apache-2.0 SRC ${PROTO_SRCS} 647 ${PROTO_HDRS}) 648 target_link_libraries(${name} PUBLIC libprotobuf) 649 target_include_directories(${name} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) 650 # Disable generation of information about every class with virtual functions 651 # for use by the C++ runtime type identification features (dynamic_cast and 652 # typeid). If you don't use those parts of the language, you can save some 653 # space by using this flag. Note that exception handling uses the same 654 # information, but it will generate it as needed. The dynamic_cast operator 655 # can still be used for casts that do not require runtime type information, 656 # i.e. casts to void * or to unambiguous base classes. 657 target_compile_options(${name} PRIVATE -fno-rtti) 658 # This needs to be public, as we don't want the headers to start exposing 659 # exceptions. 660 target_compile_definitions(${name} PUBLIC -DGOOGLE_PROTOBUF_NO_RTTI) 661 android_clang_tidy(${name}) 662endfunction() 663 664function(protobuf_generate_with_plugin) 665 include(CMakeParseArguments) 666 667 set(_options APPEND_PATH) 668 set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGINOUT PROTOPATH HEADERFILEEXTENSION) 669 if(COMMAND target_sources) 670 list(APPEND _singleargs TARGET) 671 endif() 672 set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS) 673 674 cmake_parse_arguments(protobuf_generate_with_plugin "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}") 675 676 if(NOT protobuf_generate_with_plugin_PROTOS AND NOT protobuf_generate_with_plugin_TARGET) 677 message(SEND_ERROR "Error: protobuf_generate_with_plugin called without any targets or source files") 678 return() 679 endif() 680 681 if(NOT protobuf_generate_with_plugin_OUT_VAR AND NOT protobuf_generate_with_plugin_TARGET) 682 message(SEND_ERROR "Error: protobuf_generate called without a target or output variable") 683 return() 684 endif() 685 686 if(NOT protobuf_generate_with_plugin_LANGUAGE) 687 set(protobuf_generate_with_plugin_LANGUAGE cpp) 688 endif() 689 string(TOLOWER ${protobuf_generate_with_plugin_LANGUAGE} protobuf_generate_with_plugin_LANGUAGE) 690 691 if(NOT protobuf_generate_with_plugin_PROTOC_OUT_DIR) 692 set(protobuf_generate_with_plugin_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) 693 endif() 694 695 if(protobuf_generate_with_plugin_EXPORT_MACRO AND protobuf_generate_with_plugin_LANGUAGE STREQUAL cpp) 696 set(_dll_export_decl "dllexport_decl=${protobuf_generate_with_plugin_EXPORT_MACRO}:") 697 endif() 698 699 if(NOT protobuf_generate_with_plugin_GENERATE_EXTENSIONS) 700 if(protobuf_generate_with_plugin_LANGUAGE STREQUAL cpp) 701 set(protobuf_generate_with_plugin_GENERATE_EXTENSIONS ${HEADERFILEEXTENSION} .pb.cc) 702 elseif(protobuf_generate_with_plugin_LANGUAGE STREQUAL python) 703 set(protobuf_generate_with_plugin_GENERATE_EXTENSIONS _pb2.py) 704 else() 705 message(SEND_ERROR "Error: protobuf_generatewith_plugin given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS") 706 return() 707 endif() 708 endif() 709 710 if(protobuf_generate_with_plugin_TARGET) 711 get_target_property(_source_list ${protobuf_generate_with_plugin_TARGET} SOURCES) 712 foreach(_file ${_source_list}) 713 if(_file MATCHES "proto$") 714 list(APPEND protobuf_generate_with_plugin_PROTOS ${_file}) 715 endif() 716 endforeach() 717 endif() 718 719 if(NOT protobuf_generate_with_plugin_PROTOS) 720 message(SEND_ERROR "Error: protobuf_generate_with_plugin could not find any .proto files") 721 return() 722 endif() 723 724 if(protobuf_generate_with_plugin_APPEND_PATH) 725 # Create an include path for each file specified 726 foreach(_file ${protobuf_generate_with_plugin_PROTOS}) 727 get_filename_component(_abs_file ${_file} ABSOLUTE) 728 get_filename_component(_abs_path ${_abs_file} PATH) 729 list(FIND _protobuf_include_path ${_abs_path} _contains_already) 730 if(${_contains_already} EQUAL -1) 731 list(APPEND _protobuf_include_path -I ${_abs_path}) 732 endif() 733 endforeach() 734 else() 735 set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) 736 endif() 737 738 foreach(DIR ${protobuf_generate_with_plugin_IMPORT_DIRS}) 739 get_filename_component(ABS_PATH ${DIR} ABSOLUTE) 740 list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) 741 if(${_contains_already} EQUAL -1) 742 list(APPEND _protobuf_include_path -I ${ABS_PATH}) 743 endif() 744 endforeach() 745 746 separate_arguments(PROTOPATH) 747 748 set(_generated_srcs_all) 749 foreach(_proto ${protobuf_generate_with_plugin_PROTOS}) 750 get_filename_component(_abs_file ${_proto} ABSOLUTE) 751 get_filename_component(_abs_dir ${_abs_file} DIRECTORY) 752 get_filename_component(_basename ${_proto} NAME_WE) 753 file(RELATIVE_PATH _rel_dir ${CMAKE_CURRENT_SOURCE_DIR} ${_abs_dir}) 754 755 set(_generated_srcs) 756 foreach(_ext ${protobuf_generate_with_plugin_GENERATE_EXTENSIONS}) 757 list(APPEND _generated_srcs "${protobuf_generate_with_plugin_PROTOC_OUT_DIR}/${_rel_dir}/${_basename}${_ext}") 758 endforeach() 759 list(APPEND _generated_srcs_all ${_generated_srcs}) 760 761 add_custom_command( 762 OUTPUT ${_generated_srcs} 763 COMMAND protobuf::protoc 764 ARGS --${protobuf_generate_with_plugin_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_with_plugin_PROTOC_OUT_DIR} ${_protobuf_include_path} ${PROTOPATH} ${_abs_file} --plugin=${PLUGIN} --plugin_out=${PLUGINOUT} 765 DEPENDS ${_abs_file} protobuf::protoc 766 COMMENT "Running ${protobuf_generate_with_plugin_LANGUAGE} protocol buffer compiler on ${_proto}" 767 VERBATIM ) 768 endforeach() 769 770 set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE) 771 if(protobuf_generate_with_plugin_OUT_VAR) 772 set(${protobuf_generate_with_plugin_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE) 773 endif() 774 if(protobuf_generate_with_plugin_TARGET) 775 target_sources(${protobuf_generate_with_plugin_TARGET} PRIVATE ${_generated_srcs_all}) 776 endif() 777 778endfunction() 779 780function(PROTOBUF_GENERATE_CPP_WITH_PLUGIN HEADERFILEEXTENSION PLUGIN PLUGINOUT PROTOPATH SRCS HDRS) 781 cmake_parse_arguments(protobuf_generate_cpp_with_plugin "" "EXPORT_MACRO" "" ${ARGN}) 782 783 set(_proto_files "${protobuf_generate_cpp_with_plugin_UNPARSED_ARGUMENTS}") 784 if(NOT _proto_files) 785 message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP_WITH_PLUGIN() called without any proto files") 786 return() 787 endif() 788 789 if(PROTOBUF_GENERATE_CPP_WITH_PLUGIN_APPEND_PATH) 790 set(_append_arg APPEND_PATH) 791 endif() 792 793 if(DEFINED Protobuf_IMPORT_DIRS) 794 set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS}) 795 endif() 796 797 set(_outvar) 798 protobuf_generate_with_plugin(${_append_arg} LANGUAGE cpp EXPORT_MACRO ${protobuf_generate_cpp_with_plugin_EXPORT_MACRO} OUT_VAR _outvar ${_import_arg} PROTOS ${_proto_files} PLUGIN ${PLUGIN} PLUGINOUT ${PLUGINOUT} PROTOPATH ${PROTOPATH} HEADERFILEEXTENSION ${HEADERFILEEXTENSION}) 799 800 set(${SRCS}) 801 set(${HDRS}) 802 foreach(_file ${_outvar}) 803 if(_file MATCHES "cc$") 804 list(APPEND ${SRCS} ${_file}) 805 else() 806 list(APPEND ${HDRS} ${_file}) 807 endif() 808 endforeach() 809 set(${SRCS} ${${SRCS}} PARENT_SCOPE) 810 set(${HDRS} ${${HDRS}} PARENT_SCOPE) 811endfunction() 812 813# Adds a protozero library with the given plugin name. 814function(android_add_protobuf_with_plugin name headerfileextension plugin pluginout protolib PROTOPATH protofile genccpath) 815 message( 816 WARNING "protozero protofile: ${protofile}") 817 protobuf_generate_cpp_with_plugin(${headerfileextension} ${plugin} ${pluginout} ${PROTOPATH} PROTO_SRCS PROTO_HDRS ${protofile}) 818 get_filename_component(PROTO_SRCS_ABS ${PROTO_SRCS} ABSOLUTE) 819 set(genccpath2 ${CMAKE_CURRENT_BINARY_DIR}/${genccpath}) 820 set_source_files_properties(${genccpath2} PROPERTIES GENERATED TRUE) 821 android_add_library(TARGET ${name} LICENSE Apache-2.0 SRC ${genccpath2} 822 ${PROTO_HDRS}) 823 target_link_libraries(${name} PUBLIC ${protolib}) 824 target_include_directories(${name} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) 825 # Disable generation of information about every class with virtual functions 826 # for use by the C++ runtime type identification features (dynamic_cast and 827 # typeid). If you don't use those parts of the language, you can save some 828 # space by using this flag. Note that exception handling uses the same 829 # information, but it will generate it as needed. The dynamic_cast operator 830 # can still be used for casts that do not require runtime type information, 831 # i.e. casts to void * or to unambiguous base classes. 832 target_compile_options(${name} PRIVATE -fno-rtti) 833 # This needs to be public, as we don't want the headers to start exposing 834 # exceptions. 835 target_compile_definitions(${name} PUBLIC -DGOOGLE_PROTOBUF_NO_RTTI) 836 android_clang_tidy(${name}) 837endfunction() 838 839# For adding big proto files that mingw can't handle. 840function(android_add_big_protobuf name protofiles) 841 android_add_protobuf(name protofiles) 842endfunction() 843 844# This function generates the hw config file. It translates android- 845# emu/androd/avd/hardware-properties.ini -> android/avd/hw-config-defs.h 846# 847# This file will be placed on the current binary dir, so it can be included if 848# this directory is on the include path. 849function(android_generate_hw_config) 850 set(ANDROID_HW_CONFIG_H 851 ${CMAKE_CURRENT_BINARY_DIR}/avd_config/android/avd/hw-config-defs.h) 852 add_custom_command( 853 OUTPUT ${ANDROID_HW_CONFIG_H} 854 COMMAND 855 python ${ANDROID_QEMU2_TOP_DIR}/android/scripts/gen-hw-config.py 856 ${ANDROID_QEMU2_TOP_DIR}/android/android-emu/android/avd/hardware-properties.ini 857 ${ANDROID_HW_CONFIG_H} 858 DEPENDS 859 ${ANDROID_QEMU2_TOP_DIR}/android/android-emu/android/avd/hardware-properties.ini 860 VERBATIM) 861 android_add_library(TARGET android-hw-config LICENSE Apache-2.0 862 SRC ${ANDROID_HW_CONFIG_H} dummy.c) 863 set_source_files_properties( 864 ${ANDROID_HW_CONFIG_H} 865 PROPERTIES GENERATED TRUE SKIP_AUTOGEN ON HEADER_FILE_ONLY TRUE) 866 target_include_directories(android-hw-config 867 PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/avd_config) 868endfunction() 869 870# Copies the list of test data files to the given destination The test data 871# resides in the prebuilts/android-emulator- build/common/testdata folder. 872# 873# TGT The target as part of which the test files should be copied. SOURCE_LIST 874# The list of files that need to be copied DEST The subdirectory under TGT where 875# the files should be copied to. 876function(android_copy_test_files TGT SOURCE_LIST DEST) 877 get_filename_component( 878 TESTDATA_ROOT 879 "${ANDROID_QEMU2_TOP_DIR}/../../prebuilts/android-emulator-build/common/" 880 ABSOLUTE) 881 882 foreach(SRC_FILE ${SOURCE_LIST}) 883 get_filename_component(DEST_FILE ${SRC_FILE} NAME) 884 add_custom_command( 885 TARGET ${TGT} 886 PRE_BUILD 887 COMMAND 888 ${CMAKE_COMMAND} -E copy_if_different ${TESTDATA_ROOT}/${SRC_FILE} 889 $<TARGET_FILE_DIR:${TGT}>/${DEST}/${DEST_FILE}) 890 endforeach() 891endfunction() 892 893# Copies the given file from ${SRC} -> ${DST} if needed. 894function(android_copy_file TGT SRC DST) 895 add_custom_command( 896 TARGET ${TGT} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different 897 ${SRC} ${DST} MAIN_DEPENDENCY ${SRC}) 898endfunction() 899 900# Copies the given test directory to the given destination. The test data 901# resides in the prebuilts/android-emulator- build/common/testdata folder. 902# 903# TGT The target as part of which the test files should be copied. SRC_DIR The 904# source directories to copy., DST_DIR The subdirectory under TGT where the 905# files should be copied to. 906function(android_copy_test_dir TGT SRC_DIR DST_DIR) 907 get_filename_component( 908 TESTDATA_ROOT 909 "${ANDROID_QEMU2_TOP_DIR}/../../prebuilts/android-emulator-build/common/testdata" 910 ABSOLUTE) 911 912 add_custom_command( 913 TARGET ${TGT} POST_BUILD 914 COMMAND ${CMAKE_COMMAND} -E copy_directory ${TESTDATA_ROOT}/${SRC_DIR} 915 $<TARGET_FILE_DIR:${TGT}>/${DST_DIR}) 916endfunction() 917 918# Append the given flags to the existing CMAKE_C_FLAGS. Be careful as these 919# flags are global and used for every target! Note this will not do anything 920# under vs for now 921function(add_c_flag FLGS) 922 foreach(FLAG ${FLGS}) 923 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAG}" PARENT_SCOPE) 924 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}" PARENT_SCOPE) 925 endforeach() 926endfunction() 927 928function(add_cxx_flag FLGS) 929 foreach(FLAG ${FLGS}) 930 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}" PARENT_SCOPE) 931 endforeach() 932endfunction() 933 934# This function retrieves th git_version, or reverting to the date if we cannot 935# fetch it. 936# 937# VER The variable to set the version in Sets ${VER} The version as reported by 938# git, or the date 939function(get_git_version VER) 940 execute_process( 941 COMMAND "git" "describe" WORKING_DIRECTORY ${ANDROID_QEMU2_TOP_DIR} 942 RESULT_VARIABLE GIT_RES OUTPUT_VARIABLE STD_OUT ERROR_VARIABLE STD_ERR) 943 if(NOT "${GIT_RES}" STREQUAL "0") 944 message( 945 WARNING 946 "Unable to retrieve git version from ${ANDROID_QEMU2_TOP_DIR}, out: ${STD_OUT}, err: ${STD_ERR}" 947 ) 948 if(NOT MSVC) 949 execute_process( 950 COMMAND "date" "+%Y-%m-%d" WORKING_DIRECTORY ${ANDROID_QEMU2_TOP_DIR} 951 RESULT_VARIABLE DATE_RES OUTPUT_VARIABLE STD_OUT ERROR_VARIABLE STD_ERR) 952 if(NOT "${DATE_RES}" STREQUAL "0") 953 message(FATAL_ERROR "Unable to retrieve date!") 954 endif() 955 else() 956 execute_process( 957 COMMAND "date" "/T" WORKING_DIRECTORY ${ANDROID_QEMU2_TOP_DIR} 958 RESULT_VARIABLE DATE_RES OUTPUT_VARIABLE STD_OUT ERROR_VARIABLE STD_ERR) 959 endif() 960 endif() 961 962 # Clean up and make visibile 963 string(REPLACE "\n" "" STD_OUT "${STD_OUT}") 964 set(${VER} ${STD_OUT} PARENT_SCOPE) 965endfunction() 966 967# VER The variable to set the sha in Sets ${VER} The latest sha as reported by 968# git 969function(get_git_sha VER) 970 execute_process( 971 COMMAND "git" "log" "-n" "1" "--pretty=format:'%H'" 972 WORKING_DIRECTORY ${ANDROID_QEMU2_TOP_DIR} RESULT_VARIABLE GIT_RES 973 OUTPUT_VARIABLE STD_OUT ERROR_VARIABLE STD_ERR) 974 if(NOT "${GIT_RES}" STREQUAL "0") 975 message( 976 FATAL_ERROR 977 "Unable to retrieve git version from ${ANDROID_QEMU2_TOP_DIR} : out: ${STD_OUT}, err: ${STD_ERR}" 978 ) 979 endif() 980 981 # Clean up and make visibile 982 string(REPLACE "\n" "" STD_OUT "${STD_OUT}") 983 set(${VER} ${STD_OUT} PARENT_SCOPE) 984endfunction() 985 986# Constructs a linker command that will make sure the whole archive is included, 987# not just the ones referenced. 988# 989# . LIBCMD The variable which will contain the complete linker command . LIBNAME 990# The archive that needs to be included completely 991function(android_complete_archive LIBCMD LIBNAME) 992 if(DARWIN_X86_64) 993 set(${LIBCMD} "-Wl,-force_load,$<TARGET_FILE:${LIBNAME}>" PARENT_SCOPE) 994 elseif(WINDOWS_MSVC_X86_64) 995 if(MSVC) 996 # The native build calls the linker directly 997 set(${LIBCMD} "-wholearchive:$<TARGET_FILE:${LIBNAME}>" PARENT_SCOPE) 998 else() 999 # The cross compiler calls the linker through clang. 1000 set(${LIBCMD} "-Wl,-wholearchive:$<TARGET_FILE:${LIBNAME}>" PARENT_SCOPE) 1001 endif() 1002 else() 1003 set(${LIBCMD} "-Wl,-whole-archive" ${LIBNAME} "-Wl,-no-whole-archive" 1004 PARENT_SCOPE) 1005 endif() 1006endfunction() 1007 1008# Constructs the upstream qemu executable. 1009# 1010# ANDROID_AARCH The android architecture name QEMU_AARCH The qemu architecture 1011# name. CONFIG_AARCH The configuration architecture used. STUBS The set of stub 1012# sources to use. CPU The target cpu architecture used by qemu 1013# 1014# (Maybe on one day we will standardize all the naming, between qemu and configs 1015# and cpus..) 1016function(android_build_qemu_variant) 1017 # Parse arguments 1018 set(options INSTALL) 1019 set(oneValueArgs CPU EXE) 1020 set(multiValueArgs SOURCES DEFINITIONS LIBRARIES) 1021 cmake_parse_arguments(qemu_build "${options}" "${oneValueArgs}" 1022 "${multiValueArgs}" ${ARGN}) 1023 1024 # translate various names.. because of inconsistent naming in the code base.. 1025 if(qemu_build_CPU STREQUAL "x86_64") 1026 set(CPU "i386") 1027 set(QEMU_AARCH "x86_64") 1028 set(CONFIG_AARCH "x86_64") 1029 elseif(qemu_build_CPU STREQUAL "i386") 1030 set(CPU "i386") 1031 set(QEMU_AARCH "i386") 1032 set(CONFIG_AARCH "x86") 1033 elseif(qemu_build_CPU STREQUAL "aarch64") 1034 set(CPU "arm") 1035 set(QEMU_AARCH "aarch64") 1036 set(CONFIG_AARCH "arm64") 1037 elseif(qemu_build_CPU STREQUAL "armel") 1038 set(CPU "arm") 1039 set(QEMU_AARCH "arm") 1040 set(CONFIG_AARCH "arm") 1041 else() 1042 message(FATAL_ERROR "Unknown cpu type.") 1043 endif() 1044 1045 # Workaround b/121393952, older cmake does not have proper object archives 1046 android_complete_archive(QEMU_COMPLETE_LIB "qemu2-common") 1047 android_add_executable( 1048 TARGET ${qemu_build_EXE} 1049 LICENSE Apache-2.0 1050 LIBNAME 1051 qemu-system 1052 URL 1053 "https://android.googlesource.com/platform/external/qemu/+/refs/heads/emu-master-dev" 1054 REPO "${ANDROID_QEMU2_TOP_DIR}" 1055 NOTICE "REPO/LICENSES/LICENSE.APACHE2" 1056 SRC ${qemu_build_SOURCES} ${qemu-system-${QEMU_AARCH}_sources} 1057 ${qemu-system-${QEMU_AARCH}_generated_sources}) 1058 target_include_directories( 1059 ${qemu_build_EXE} PRIVATE android-qemu2-glue/config/target-${CONFIG_AARCH} 1060 target/${CPU}) 1061 target_compile_definitions(${qemu_build_EXE} 1062 PRIVATE ${qemu_build_DEFINITIONS}) 1063 target_link_libraries(${qemu_build_EXE} PRIVATE ${QEMU_COMPLETE_LIB} 1064 ${qemu_build_LIBRARIES}) 1065 1066 # Make the common dependency explicit, as some generators might not detect it 1067 # properly (Xcode/MSVC native) 1068 add_dependencies(${qemu_build_EXE} qemu2-common) 1069 # XCode bin places this not where we want this... 1070 if(qemu_build_INSTALL) 1071 set_target_properties( 1072 ${qemu_build_EXE} 1073 PROPERTIES 1074 RUNTIME_OUTPUT_DIRECTORY 1075 "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/qemu/${ANDROID_TARGET_OS_FLAVOR}-${ANDROID_TARGET_ARCH}" 1076 ) 1077 android_install_exe(${qemu_build_EXE} 1078 "./qemu/${ANDROID_TARGET_OS_FLAVOR}-${ANDROID_TARGET_ARCH}") 1079 endif() 1080endfunction() 1081 1082# Constructs the qemu executable. 1083# 1084# ANDROID_AARCH The android architecture name STUBS The set of stub sources to 1085# use. 1086function(android_add_qemu_executable ANDROID_AARCH STUBS) 1087 if (WINDOWS_MSVC_X86_64) 1088 set(WINDOWS_LAUNCHER emulator-winqt-launcher) 1089 endif() 1090 android_build_qemu_variant( 1091 INSTALL 1092 EXE qemu-system-${ANDROID_AARCH} 1093 CPU ${ANDROID_AARCH} 1094 SOURCES android-qemu2-glue/main.cpp vl.c ${STUBS} 1095 DEFINITIONS 1096 -DNEED_CPU_H -DCONFIG_ANDROID 1097 -DANDROID_SDK_TOOLS_REVISION=${OPTION_SDK_TOOLS_REVISION} 1098 -DANDROID_SDK_TOOLS_BUILD_NUMBER=${OPTION_SDK_TOOLS_BUILD_NUMBER} 1099 LIBRARIES libqemu2-glue 1100 libqemu2-glue-vm-operations 1101 libqemu2-util 1102 emulator-libui 1103 android-emu 1104 android-qemu-deps 1105 android-qemu-deps-headful 1106 emulator-libusb 1107 ${WINDOWS_LAUNCHER}) 1108endfunction() 1109 1110# Constructs the qemu headless executable. 1111# 1112# ANDROID_AARCH The android architecture name STUBS The set of stub sources to 1113# use. 1114function(android_add_qemu_headless_executable ANDROID_AARCH STUBS) 1115 android_build_qemu_variant( 1116 INSTALL 1117 EXE qemu-system-${ANDROID_AARCH}-headless 1118 CPU ${ANDROID_AARCH} 1119 SOURCES android-qemu2-glue/main.cpp vl.c ${STUBS} 1120 DEFINITIONS 1121 -DNEED_CPU_H -DCONFIG_ANDROID -DCONFIG_HEADLESS 1122 -DANDROID_SDK_TOOLS_REVISION=${OPTION_SDK_TOOLS_REVISION} 1123 -DANDROID_SDK_TOOLS_BUILD_NUMBER=${OPTION_SDK_TOOLS_BUILD_NUMBER} 1124 LIBRARIES libqemu2-glue 1125 libqemu2-glue-vm-operations 1126 libqemu2-util 1127 android-emu 1128 emulator-libui-headless 1129 android-qemu-deps 1130 android-qemu-deps-headless 1131 emulator-libusb) 1132endfunction() 1133 1134# Constructs the qemu upstream executable. 1135# 1136# ANDROID_AARCH The android architecture name STUBS The set of stub sources to 1137# use. 1138function(android_add_qemu_upstream_executable ANDROID_AARCH STUBS) 1139 android_build_qemu_variant( 1140 # INSTALL We do not install this target. 1141 EXE qemu-upstream-${ANDROID_AARCH} 1142 CPU ${ANDROID_AARCH} 1143 SOURCES vl.c ${STUBS} 1144 DEFINITIONS -DNEED_CPU_H 1145 LIBRARIES android-emu 1146 libqemu2-glue 1147 libqemu2-glue-vm-operations 1148 libqemu2-util 1149 SDL2::SDL2 1150 android-qemu-deps 1151 android-qemu-deps-headful 1152 emulator-libusb) 1153endfunction() 1154 1155# Copies a shared library 1156function(android_copy_shared_lib TGT SHARED_LIB NAME) 1157 android_copy_file( 1158 ${TGT} $<TARGET_FILE:${SHARED_LIB}> 1159 $<TARGET_FILE_DIR:${TGT}>/lib64/${NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) 1160endfunction() 1161 1162function(android_log MSG) 1163 if(ANDROID_LOG) 1164 message(STATUS ${MSG}) 1165 endif() 1166endfunction() 1167 1168function(android_validate_sha256 FILE EXPECTED) 1169 file(SHA256 ${FILE} CHECKSUM) 1170 if(NOT CHECKSUM STREQUAL "${EXPECTED}") 1171 get_filename_component( 1172 DEST "${ANDROID_QEMU2_TOP_DIR}/../../device/generic/goldfish-opengl" 1173 ABSOLUTE) 1174 message( 1175 FATAL_ERROR 1176 "Checksum mismatch for ${FILE} = ${CHECKSUM}, expecting ${EXPECTED}, you need to regenerate the cmake files by executing 'make' in ${DEST}" 1177 ) 1178 endif() 1179endfunction() 1180 1181# Uploads the symbols to the breakpad crash server 1182function(android_upload_symbols TGT) 1183 find_package(PythonInterp) 1184 if(NOT ANDROID_EXTRACT_SYMBOLS) 1185 return() 1186 endif() 1187 set(DEST "${ANDROID_SYMBOL_DIR}/${TGT}.sym") 1188 set(LOG "${ANDROID_SYMBOL_DIR}/${TGT}.log") 1189 install( 1190 CODE # Upload the symbols, with warnings/error logging only. 1191 "execute_process(COMMAND \"${PYTHON_EXECUTABLE}\" 1192 \"${ANDROID_QEMU2_TOP_DIR}/android/build/python/aemu/upload_symbols.py\" 1193 \"--symbol_file\" \"${DEST}\" 1194 \"--environment\" \"${OPTION_CRASHUPLOAD}\" 1195 OUTPUT_FILE ${LOG} 1196 ERROR_FILE ${LOG})\n 1197 if (EXISTS ${LOG}) 1198 FILE(READ ${LOG} contents) 1199 STRING(STRIP \"\$\{contents\}\" contents) 1200 else() 1201 SET(contents \"No logfile in ${LOG} for ${DEST} was created\") 1202 endif() 1203 MESSAGE(STATUS \$\{contents\})") 1204endfunction() 1205 1206# Installs the given target executable into the given destinations. Symbols will 1207# be extracted during build, and uploaded during install. 1208function(android_install_exe TGT) 1209 install(TARGETS ${TGT} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) 1210 1211 # Make it available on the build server 1212 # android_extract_symbols(${TGT}) 1213 # android_upload_symbols(${TGT}) 1214 # android_install_license(${TGT} ${DST}/${TGT}${CMAKE_EXECUTABLE_SUFFIX}) 1215endfunction() 1216 1217# Installs the given shared library. The shared library will end up in ../lib64 1218# Symbols will be extracted during build, and uploaded during install. 1219function(android_install_shared TGT) 1220 install( 1221 TARGETS ${TGT} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}) 1222 # android_extract_symbols(${TGT}) 1223 # android_upload_symbols(${TGT}) 1224 # android_install_license(${TGT} ${TGT}${CMAKE_SHARED_LIBRARY_SUFFIX}) 1225endfunction() 1226 1227# Strips the given prebuilt executable during install.. 1228function(android_strip_prebuilt FNAME) 1229 # MSVC stores debug info in seperate file, so no need to strip 1230 if(NOT WINDOWS_MSVC_X86_64) 1231 install( 1232 CODE "if(CMAKE_INSTALL_DO_STRIP) \n 1233 execute_process(COMMAND ${CMAKE_STRIP} \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${FNAME}\")\n 1234 endif()\n 1235 ") 1236 endif() 1237endfunction() 1238 1239# Extracts symbols from a file that is not built. This is mainly here if we wish 1240# to extract symbols for a prebuilt file. 1241function(android_extract_symbols_file FNAME) 1242 get_filename_component(BASENAME ${FNAME} NAME) 1243 set(DEST "${ANDROID_SYMBOL_DIR}/${BASENAME}.sym") 1244 1245 if(WINDOWS_MSVC_X86_64) 1246 # In msvc we need the pdb to generate the symbols, pdbs are not yet 1247 # available for The prebuilts. b/122728651 1248 message( 1249 WARNING 1250 "Extracting symbols requires access to the pdb for ${FNAME}, ignoring for now." 1251 ) 1252 return() 1253 endif() 1254 install( 1255 CODE "execute_process(COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/dump_syms -g ${FNAME} OUTPUT_FILE ${DEST} RESULT_VARIABLE RES ERROR_QUIET) \n 1256 message(STATUS \"Extracted symbols for ${FNAME} ${RES}\")") 1257 install( 1258 CODE "execute_process(COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sym_upload ${DEST} ${ANDROID_SYMBOL_URL} OUTPUT_VARIABLE RES ERROR_QUIET) \n 1259 message(STATUS \"Uploaded symbols for ${FNAME} --> ${ANDROID_SYMBOL_URL} ${RES}\")" 1260 ) 1261endfunction() 1262 1263# Extracts the symbols from the given target if extraction is requested. TODO: 1264# We need generator expressions to move this to the install phase. Which are 1265# available in cmake 3.13 1266function(android_extract_symbols TGT) 1267 if(NOT ANDROID_EXTRACT_SYMBOLS) 1268 # Note: we do not need to extract symbols on windows for uploading. 1269 return() 1270 endif() 1271 set(DEST "${ANDROID_SYMBOL_DIR}/${TGT}.sym") 1272 add_custom_command( 1273 TARGET ${TGT} POST_BUILD COMMAND dump_syms "$<TARGET_FILE:${TGT}>" > ${DEST} 1274 DEPENDS dump_syms 1275 COMMENT "Extracting symbols for ${TGT}" VERBATIM) 1276endfunction() 1277 1278# Make the compatibility layer available for every target 1279if(WINDOWS_MSVC_X86_64 AND NOT INCLUDE_MSVC_POSIX) 1280 set(INCLUDE_MSVC_POSIX 1) 1281 add_subdirectory(${ANDROID_QEMU2_TOP_DIR}/android/msvc-posix-compat/ 1282 msvc-posix-compat) 1283endif() 1284 1285# Rule to build cf crosvm based on a combination of dependencies 1286# built locally / prebuilt 1287function(android_crosvm_build DEP) 1288 message(STATUS "building crosvm with dependency ${DEP}") 1289 set(CMAKE_CROSVM_HOST_PACKAGE_TOOLS_PATH 1290 "${ANDROID_QEMU2_TOP_DIR}/../../prebuilts/android-emulator-build/common/cf-host-package") 1291 set(CMAKE_CROSVM_BUILD_SCRIPT_PATH 1292 "${CMAKE_CROSVM_HOST_PACKAGE_TOOLS_PATH}/crosvm-build.sh") 1293 1294 set(CMAKE_CROSVM_REPO_TOP_LEVEL_PATH 1295 "${ANDROID_QEMU2_TOP_DIR}/../..") 1296 set(CMAKE_CROSVM_BUILD_ENV_DIR 1297 "${CMAKE_BINARY_DIR}/crosvm-build-env") 1298 set(CMAKE_CROSVM_GFXSTREAM_BUILD_DIR 1299 "${CMAKE_BINARY_DIR}") 1300 set(CMAKE_CROSVM_DIST_DIR 1301 "${CMAKE_INSTALL_PREFIX}") 1302 add_custom_command( 1303 OUTPUT "${CMAKE_CROSVM_BUILD_ENV_DIR}/release/crosvm" 1304 COMMAND 1305 "${CMAKE_CROSVM_BUILD_SCRIPT_PATH}" 1306 "${CMAKE_CROSVM_REPO_TOP_LEVEL_PATH}" 1307 "${CMAKE_CROSVM_HOST_PACKAGE_TOOLS_PATH}" 1308 "${CMAKE_CROSVM_BUILD_ENV_DIR}" 1309 "${CMAKE_CROSVM_GFXSTREAM_BUILD_DIR}" 1310 "${CMAKE_CROSVM_DIST_DIR}" 1311 DEPENDS ${DEP}) 1312endfunction() 1313