1*ec63e07aSXin Li# Copyright 2019 Google LLC 2*ec63e07aSXin Li# 3*ec63e07aSXin Li# Licensed under the Apache License, Version 2.0 (the "License"); 4*ec63e07aSXin Li# you may not use this file except in compliance with the License. 5*ec63e07aSXin Li# You may obtain a copy of the License at 6*ec63e07aSXin Li# 7*ec63e07aSXin Li# https://www.apache.org/licenses/LICENSE-2.0 8*ec63e07aSXin Li# 9*ec63e07aSXin Li# Unless required by applicable law or agreed to in writing, software 10*ec63e07aSXin Li# distributed under the License is distributed on an "AS IS" BASIS, 11*ec63e07aSXin Li# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*ec63e07aSXin Li# See the License for the specific language governing permissions and 13*ec63e07aSXin Li# limitations under the License. 14*ec63e07aSXin Li 15*ec63e07aSXin Li# Embeds arbitrary binary data into a static library. 16*ec63e07aSXin Li# 17*ec63e07aSXin Li# NAME specifies the name for this target. 18*ec63e07aSXin Li# NAMESPACE is the C++ namespace the generated code is placed in. Can be empty. 19*ec63e07aSXin Li# SOURCES is a list of files that should be embedded. If a source names a 20*ec63e07aSXin Li# target the target binary is embedded instead. 21*ec63e07aSXin Limacro(sapi_cc_embed_data) 22*ec63e07aSXin Li cmake_parse_arguments(_sapi_embed "" "OUTPUT_NAME;NAME;NAMESPACE" "SOURCES" 23*ec63e07aSXin Li ${ARGN}) 24*ec63e07aSXin Li foreach(src IN LISTS _sapi_embed_SOURCES) 25*ec63e07aSXin Li if(TARGET "${src}") 26*ec63e07aSXin Li get_target_property(_sapi_embed_src_OUTPUT_NAME ${src} OUTPUT_NAME) 27*ec63e07aSXin Li if(NOT _sapi_embed_src_OUTPUT_NAME) 28*ec63e07aSXin Li set(_sapi_embed_src_OUTPUT_NAME "${src}") 29*ec63e07aSXin Li endif() 30*ec63e07aSXin Li list(APPEND _sapi_embed_in 31*ec63e07aSXin Li "${CMAKE_CURRENT_BINARY_DIR}/${_sapi_embed_src_OUTPUT_NAME}") 32*ec63e07aSXin Li else() 33*ec63e07aSXin Li list(APPEND _sapi_embed_in "${src}") 34*ec63e07aSXin Li endif() 35*ec63e07aSXin Li endforeach() 36*ec63e07aSXin Li file(RELATIVE_PATH _sapi_embed_pkg 37*ec63e07aSXin Li "${PROJECT_BINARY_DIR}" 38*ec63e07aSXin Li "${CMAKE_CURRENT_BINARY_DIR}") 39*ec63e07aSXin Li if(NOT _sapi_embed_OUTPUT_NAME) 40*ec63e07aSXin Li set(_sapi_embed_OUTPUT_NAME "${_sapi_embed_NAME}") 41*ec63e07aSXin Li endif() 42*ec63e07aSXin Li add_custom_command( 43*ec63e07aSXin Li OUTPUT "${_sapi_embed_OUTPUT_NAME}.h" 44*ec63e07aSXin Li "${_sapi_embed_OUTPUT_NAME}.cc" 45*ec63e07aSXin Li WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 46*ec63e07aSXin Li COMMAND filewrapper "${_sapi_embed_pkg}" 47*ec63e07aSXin Li "${_sapi_embed_OUTPUT_NAME}" 48*ec63e07aSXin Li "${_sapi_embed_NAMESPACE}" 49*ec63e07aSXin Li "${CMAKE_CURRENT_BINARY_DIR}/${_sapi_embed_OUTPUT_NAME}.h" 50*ec63e07aSXin Li "${CMAKE_CURRENT_BINARY_DIR}/${_sapi_embed_OUTPUT_NAME}.cc" 51*ec63e07aSXin Li ${_sapi_embed_in} 52*ec63e07aSXin Li DEPENDS ${_sapi_embed_SOURCES} 53*ec63e07aSXin Li VERBATIM 54*ec63e07aSXin Li ) 55*ec63e07aSXin Li add_library("${_sapi_embed_NAME}" STATIC 56*ec63e07aSXin Li "${_sapi_embed_OUTPUT_NAME}.h" 57*ec63e07aSXin Li "${_sapi_embed_OUTPUT_NAME}.cc" 58*ec63e07aSXin Li ) 59*ec63e07aSXin Li target_link_libraries("${_sapi_embed_NAME}" PRIVATE 60*ec63e07aSXin Li sapi::base 61*ec63e07aSXin Li absl::core_headers 62*ec63e07aSXin Li ) 63*ec63e07aSXin Liendmacro() 64*ec63e07aSXin Li 65*ec63e07aSXin Li# Adds a library target implementing a sandboxed API for another library. 66*ec63e07aSXin Li# The first argument is the target name, similar to the native add_library(). 67*ec63e07aSXin Li# This function implements the same functionality as the Bazel version in 68*ec63e07aSXin Li# sandboxed_api/bazel/sapi.bzl. 69*ec63e07aSXin Li# 70*ec63e07aSXin Li# SOURCES Any additional sources to include with the Sandboxed API library. 71*ec63e07aSXin Li# Typically not necessary, unless the sandbox definition should be in a .cc 72*ec63e07aSXin Li# file instead of the customary "sandbox.h" header. Bazel also has a "hdrs" 73*ec63e07aSXin Li# attribute, but CMake does not distinguish headers from sources. 74*ec63e07aSXin Li# FUNCTIONS A list of functions that to use in from host code. Leaving this 75*ec63e07aSXin Li# list empty will export and wrap all functions found in the library. 76*ec63e07aSXin Li# NOEMBED Whether the SAPI library should be embedded inside host code, so the 77*ec63e07aSXin Li# SAPI Sandbox can be initialized with the 78*ec63e07aSXin Li# ::sapi::Sandbox::Sandbox(FileToc*) constructor. 79*ec63e07aSXin Li# LIBRARY The library target to sandbox and expose to the host code (required). 80*ec63e07aSXin Li# LIBRARY_NAME The name of the class which will proxy the library functions 81*ec63e07aSXin Li# from the functions list (required). You will call functions from the 82*ec63e07aSXin Li# sandboxed library via instances of this class. 83*ec63e07aSXin Li# INPUTS List of source files which the SAPI interface generator should scan 84*ec63e07aSXin Li# for function declarations. Library header files are always scanned, so 85*ec63e07aSXin Li# this can usually be empty/omitted. 86*ec63e07aSXin Li# NAMESPACE C++ namespace identifier to place API class defined by 87*ec63e07aSXin Li# LIBRARY_NAME into. 88*ec63e07aSXin Li# HEADER If set, does not generate an interface header, but uses the one 89*ec63e07aSXin Li# specified. 90*ec63e07aSXin Li# API_VERSION Which version of the Sandboxed API to generate. Currently, only 91*ec63e07aSXin Li# version "1" is defined. 92*ec63e07aSXin Lifunction(add_sapi_library) 93*ec63e07aSXin Li set(_sapi_opts NOEMBED) 94*ec63e07aSXin Li set(_sapi_one_value HEADER LIBRARY LIBRARY_NAME NAMESPACE API_VERSION) 95*ec63e07aSXin Li set(_sapi_multi_value SOURCES FUNCTIONS INPUTS) 96*ec63e07aSXin Li cmake_parse_arguments(PARSE_ARGV 0 _sapi "${_sapi_opts}" 97*ec63e07aSXin Li "${_sapi_one_value}" "${_sapi_multi_value}") 98*ec63e07aSXin Li set(_sapi_NAME "${ARGV0}") 99*ec63e07aSXin Li 100*ec63e07aSXin Li if(_sapi_API_VERSION AND NOT _sapi_API_VERSION VERSION_EQUAL "1") 101*ec63e07aSXin Li message(FATAL_ERROR "API_VERSION \"1\" is the only one defined right now") 102*ec63e07aSXin Li endif() 103*ec63e07aSXin Li 104*ec63e07aSXin Li set(_sapi_gen_header "${_sapi_NAME}.sapi.h") 105*ec63e07aSXin Li foreach(func IN LISTS _sapi_FUNCTIONS) 106*ec63e07aSXin Li list(APPEND _sapi_exported_funcs "LINKER:--export-dynamic-symbol,${func}") 107*ec63e07aSXin Li endforeach() 108*ec63e07aSXin Li if(NOT _sapi_exported_funcs) 109*ec63e07aSXin Li set(_sapi_exported_funcs LINKER:--allow-multiple-definition) 110*ec63e07aSXin Li endif() 111*ec63e07aSXin Li 112*ec63e07aSXin Li # The sandboxed binary 113*ec63e07aSXin Li set(_sapi_bin "${_sapi_NAME}.bin") 114*ec63e07aSXin Li add_executable("${_sapi_bin}" 115*ec63e07aSXin Li "${SAPI_BINARY_DIR}/sapi_force_cxx_linkage.cc" 116*ec63e07aSXin Li ) 117*ec63e07aSXin Li target_link_libraries("${_sapi_bin}" PRIVATE 118*ec63e07aSXin Li -fuse-ld=gold 119*ec63e07aSXin Li -Wl,--whole-archive "${_sapi_LIBRARY}" -Wl,--no-whole-archive 120*ec63e07aSXin Li # Needs to be whole-archive due to how it Abseil registers flags 121*ec63e07aSXin Li -Wl,--whole-archive absl::log_flags -Wl,--no-whole-archive 122*ec63e07aSXin Li sapi::client 123*ec63e07aSXin Li ${CMAKE_DL_LIBS} 124*ec63e07aSXin Li ) 125*ec63e07aSXin Li target_link_options("${_sapi_bin}" PRIVATE 126*ec63e07aSXin Li LINKER:-E 127*ec63e07aSXin Li ${_sapi_exported_funcs} 128*ec63e07aSXin Li ) 129*ec63e07aSXin Li 130*ec63e07aSXin Li if(NOT _sapi_NOEMBED) 131*ec63e07aSXin Li set(_sapi_embed "${_sapi_NAME}_embed") 132*ec63e07aSXin Li sapi_cc_embed_data(NAME "${_sapi_embed}" 133*ec63e07aSXin Li NAMESPACE "${_sapi_NAMESPACE}" 134*ec63e07aSXin Li SOURCES "${_sapi_bin}" 135*ec63e07aSXin Li ) 136*ec63e07aSXin Li endif() 137*ec63e07aSXin Li 138*ec63e07aSXin Li # Interface 139*ec63e07aSXin Li list(JOIN _sapi_FUNCTIONS "," _sapi_funcs) 140*ec63e07aSXin Li foreach(src IN LISTS _sapi_INPUTS) 141*ec63e07aSXin Li get_filename_component(src "${src}" ABSOLUTE) 142*ec63e07aSXin Li list(APPEND _sapi_full_inputs "${src}") 143*ec63e07aSXin Li endforeach() 144*ec63e07aSXin Li if(NOT _sapi_NOEMBED) 145*ec63e07aSXin Li set(_sapi_embed_dir "${CMAKE_CURRENT_BINARY_DIR}") 146*ec63e07aSXin Li set(_sapi_embed_name "${_sapi_NAME}") 147*ec63e07aSXin Li endif() 148*ec63e07aSXin Li 149*ec63e07aSXin Li list(APPEND _sapi_generator_args 150*ec63e07aSXin Li "--sapi_name=${_sapi_LIBRARY_NAME}" 151*ec63e07aSXin Li "--sapi_out=${_sapi_gen_header}" 152*ec63e07aSXin Li "--sapi_embed_dir=${_sapi_embed_dir}" 153*ec63e07aSXin Li "--sapi_embed_name=${_sapi_embed_name}" 154*ec63e07aSXin Li "--sapi_functions=${_sapi_funcs}" 155*ec63e07aSXin Li "--sapi_ns=${_sapi_NAMESPACE}" 156*ec63e07aSXin Li ) 157*ec63e07aSXin Li if(SAPI_ENABLE_CLANG_TOOL) 158*ec63e07aSXin Li set(_sapi_isystem_args ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) 159*ec63e07aSXin Li list(TRANSFORM _sapi_isystem_args PREPEND --extra-arg-before=-isystem) 160*ec63e07aSXin Li if(SAPI_CLANG_TOOL_EXECUTABLE) 161*ec63e07aSXin Li list(APPEND _sapi_generator_command "${SAPI_CLANG_TOOL_EXECUTABLE}") 162*ec63e07aSXin Li else() 163*ec63e07aSXin Li list(APPEND _sapi_generator_command sapi_generator_tool) 164*ec63e07aSXin Li endif() 165*ec63e07aSXin Li list(APPEND _sapi_generator_command 166*ec63e07aSXin Li -p "${CMAKE_CURRENT_BINARY_DIR}" 167*ec63e07aSXin Li ${_sapi_generator_args} 168*ec63e07aSXin Li ${_sapi_isystem_args} 169*ec63e07aSXin Li ${_sapi_full_inputs} 170*ec63e07aSXin Li ) 171*ec63e07aSXin Li add_custom_command( 172*ec63e07aSXin Li OUTPUT "${_sapi_gen_header}" 173*ec63e07aSXin Li COMMAND ${_sapi_generator_command} 174*ec63e07aSXin Li COMMENT "Generating interface" 175*ec63e07aSXin Li DEPENDS ${_sapi_INPUTS} 176*ec63e07aSXin Li VERBATIM 177*ec63e07aSXin Li ) 178*ec63e07aSXin Li else() 179*ec63e07aSXin Li set(_sapi_isystem "${_sapi_NAME}.isystem") 180*ec63e07aSXin Li list(JOIN _sapi_full_inputs "," _sapi_full_inputs) 181*ec63e07aSXin Li list(APPEND _sapi_generator_command 182*ec63e07aSXin Li "${SAPI_PYTHON3_EXECUTABLE}" -B 183*ec63e07aSXin Li "${SAPI_SOURCE_DIR}/sandboxed_api/tools/generator2/sapi_generator.py" 184*ec63e07aSXin Li ${_sapi_generator_args} 185*ec63e07aSXin Li "--sapi_isystem=${_sapi_isystem}" 186*ec63e07aSXin Li "--sapi_in=${_sapi_full_inputs}" 187*ec63e07aSXin Li ) 188*ec63e07aSXin Li add_custom_command( 189*ec63e07aSXin Li OUTPUT "${_sapi_gen_header}" "${_sapi_isystem}" 190*ec63e07aSXin Li COMMAND sh -c 191*ec63e07aSXin Li "printf '${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}' | \ 192*ec63e07aSXin Li sed \"s/;/\\n/g\" > \"${_sapi_isystem}\"" 193*ec63e07aSXin Li COMMAND ${_sapi_generator_command} 194*ec63e07aSXin Li COMMENT "Generating interface" 195*ec63e07aSXin Li DEPENDS ${_sapi_INPUTS} 196*ec63e07aSXin Li VERBATIM 197*ec63e07aSXin Li ) 198*ec63e07aSXin Li endif() 199*ec63e07aSXin Li 200*ec63e07aSXin Li # Library with the interface 201*ec63e07aSXin Li if(NOT _sapi_SOURCES) 202*ec63e07aSXin Li list(APPEND _sapi_SOURCES 203*ec63e07aSXin Li "${SAPI_BINARY_DIR}/sapi_force_cxx_linkage.cc" 204*ec63e07aSXin Li ) 205*ec63e07aSXin Li endif() 206*ec63e07aSXin Li add_library("${_sapi_NAME}" STATIC 207*ec63e07aSXin Li "${_sapi_gen_header}" 208*ec63e07aSXin Li ${_sapi_SOURCES} 209*ec63e07aSXin Li ) 210*ec63e07aSXin Li target_link_libraries("${_sapi_NAME}" PUBLIC 211*ec63e07aSXin Li absl::status 212*ec63e07aSXin Li absl::statusor 213*ec63e07aSXin Li sapi::sapi 214*ec63e07aSXin Li sapi::status 215*ec63e07aSXin Li sapi::vars 216*ec63e07aSXin Li ) 217*ec63e07aSXin Li if(NOT _sapi_NOEMBED) 218*ec63e07aSXin Li target_link_libraries("${_sapi_NAME}" PUBLIC 219*ec63e07aSXin Li "${_sapi_embed}" 220*ec63e07aSXin Li ) 221*ec63e07aSXin Li endif() 222*ec63e07aSXin Liendfunction() 223*ec63e07aSXin Li 224*ec63e07aSXin Li# Wrapper for gtest_discover_tests to exclude tests discover when cross compiling. 225*ec63e07aSXin Limacro(gtest_discover_tests_xcompile) 226*ec63e07aSXin Li if (NOT CMAKE_CROSSCOMPILING) 227*ec63e07aSXin Li gtest_discover_tests(${ARGV}) 228*ec63e07aSXin Li endif() 229*ec63e07aSXin Liendmacro() 230