c/cmake_modules/GoUtils.cmake (224 lines of code) (raw):
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
find_program(GO_BIN "go" REQUIRED)
message(STATUS "Detecting Go executable: Found ${GO_BIN}")
function(add_go_lib GO_MOD_DIR GO_LIBNAME)
set(options)
set(one_value_args
BUILD_TAGS
SHARED_LINK_FLAGS
CMAKE_PACKAGE_NAME
PKG_CONFIG_NAME
BUILD_STATIC
BUILD_SHARED)
set(multi_value_args SOURCES OUTPUTS)
cmake_parse_arguments(ARG
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
endif()
if(ARG_OUTPUTS)
set(${ARG_OUTPUTS})
endif()
# Allow overriding ADBC_BUILD_SHARED and ADBC_BUILD_STATIC
if(DEFINED ARG_BUILD_SHARED)
set(BUILD_SHARED ${ARG_BUILD_SHARED})
else()
set(BUILD_SHARED ${ADBC_BUILD_SHARED})
endif()
if(DEFINED ARG_BUILD_STATIC)
set(BUILD_STATIC ${ARG_BUILD_STATIC})
else()
set(BUILD_STATIC ${ADBC_BUILD_STATIC})
endif()
set(BUILD_TAGS)
if(DEFINED ARG_BUILD_TAGS)
set(BUILD_TAGS "${ARG_BUILD_TAGS}")
endif()
if(NOT "${ADBC_GO_BUILD_TAGS}" STREQUAL "")
if(NOT "${BUILD_TAGS}" STREQUAL "")
set(BUILD_TAGS "${BUILD_TAGS},")
endif()
set(BUILD_TAGS "${BUILD_TAGS}${ADBC_GO_BUILD_TAGS}")
endif()
if(NOT "${BUILD_TAGS}" STREQUAL "")
set(GO_BUILD_TAGS "-tags=${BUILD_TAGS}")
endif()
list(TRANSFORM ARG_SOURCES PREPEND "${GO_MOD_DIR}/")
# go asan only works on linux/amd64 and linux/arm64
if(ADBC_USE_ASAN)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
if(NOT APPLE AND NOT MSVC_TOOLCHAIN)
set(GO_BUILD_FLAGS "-asan")
endif()
endif()
endif()
# Go gcflags for disabling optimizations and inlining if debug
separate_arguments(GO_BUILD_FLAGS NATIVE_COMMAND
"${GO_BUILD_FLAGS} $<$<CONFIG:DEBUG>:-gcflags=\"-N -l\">")
# if we're building debug mode then change the default CGO_CFLAGS and CGO_CXXFLAGS from "-g O2" to "-g3"
set(GO_ENV_VARS
"CGO_ENABLED=1 $<$<CONFIG:DEBUG>:CGO_CFLAGS=-g3> $<$<CONFIG:DEBUG>:CGO_CXXFLAGS=-g3>"
)
separate_arguments(GO_ENV_VARS NATIVE_COMMAND "${GO_ENV_VARS}")
if(BUILD_SHARED)
set(LIB_NAME_SHARED
"${CMAKE_SHARED_LIBRARY_PREFIX}${GO_LIBNAME}${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(ADBC_VERSION_SCRIPT_LINK_FLAG
"-Wl,--version-script=${REPOSITORY_ROOT}/c/symbols.map")
check_linker_flag(CXX ${ADBC_VERSION_SCRIPT_LINK_FLAG}
CXX_LINKER_SUPPORTS_VERSION_SCRIPT)
if(CXX_LINKER_SUPPORTS_VERSION_SCRIPT)
set(EXTLDFLAGS ",--version-script=${REPOSITORY_ROOT}/c/symbols.map")
endif()
if(NOT APPLE)
set(EXTLDFLAGS "${EXTLDFLAGS},-soname,${LIB_NAME_SHARED}.${ADBC_SO_VERSION}")
endif()
if(DEFINED EXTLDFLAGS)
set(EXTLDFLAGS "'-extldflags=-Wl${EXTLDFLAGS}'")
endif()
if(DEFINED ARG_SHARED_LINK_FLAGS)
separate_arguments(ARG_SHARED_LINK_FLAGS NATIVE_COMMAND "${ARG_SHARED_LINK_FLAGS}")
endif()
set(GO_LDFLAGS "-ldflags;\"${ARG_SHARED_LINK_FLAGS};-a;${EXTLDFLAGS}\"")
set(LIBOUT_SHARED "${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME_SHARED}")
if(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
list(APPEND GO_ENV_VARS "GOARCH=amd64")
elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
list(APPEND GO_ENV_VARS "GOARCH=arm64")
endif()
add_custom_command(OUTPUT "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
WORKING_DIRECTORY ${GO_MOD_DIR}
DEPENDS ${ARG_SOURCES}
COMMAND ${CMAKE_COMMAND} -E env ${GO_ENV_VARS} ${GO_BIN} build
${GO_BUILD_TAGS} "${GO_BUILD_FLAGS}" -o
${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}
-buildmode=c-shared ${GO_LDFLAGS} .
COMMAND ${CMAKE_COMMAND} -E remove -f
"${LIBOUT_SHARED}.${ADBC_SO_VERSION}.0.h"
COMMENT "Building Go Shared lib ${GO_LIBNAME}"
COMMAND_EXPAND_LISTS)
add_custom_command(OUTPUT "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" "${LIBOUT_SHARED}"
DEPENDS "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E create_symlink
"${LIB_NAME_SHARED}.${ADBC_FULL_SO_VERSION}"
"${LIB_NAME_SHARED}.${ADBC_SO_VERSION}"
COMMAND ${CMAKE_COMMAND} -E create_symlink
"${LIB_NAME_SHARED}.${ADBC_SO_VERSION}"
"${LIB_NAME_SHARED}")
add_custom_target(${GO_LIBNAME}_target ALL
DEPENDS "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
"${LIBOUT_SHARED}.${ADBC_SO_VERSION}" "${LIBOUT_SHARED}")
add_library(${GO_LIBNAME}_shared SHARED IMPORTED)
set_target_properties(${GO_LIBNAME}_shared
PROPERTIES IMPORTED_LOCATION
"${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
IMPORTED_SONAME "${LIB_NAME_SHARED}")
add_dependencies(${GO_LIBNAME}_shared ${GO_LIBNAME}_target)
if(ARG_OUTPUTS)
list(APPEND ${ARG_OUTPUTS} ${GO_LIBNAME}_shared)
endif()
if(ADBC_RPATH_ORIGIN)
if(APPLE)
set(_lib_install_rpath "@loader_path")
else()
set(_lib_install_rpath "\$ORIGIN")
endif()
set_target_properties(${GO_LIBNAME}_shared PROPERTIES INSTALL_RPATH
${_lib_install_rpath})
endif()
if(APPLE)
if(ADBC_INSTALL_NAME_RPATH)
set(_lib_install_name "@rpath")
else()
set(_lib_install_name "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
endif()
set_target_properties(${GO_LIBNAME}_shared PROPERTIES INSTALL_NAME_DIR
"${_lib_install_name}")
endif()
if(CMAKE_VERSION VERSION_LESS "3.21")
if(WIN32)
install(PROGRAMS $<TARGET_FILE:${GO_LIBNAME}_shared> ${INSTALL_IS_OPTIONAL}
DESTINATION ${RUNTIME_INSTALL_DIR})
else()
install(PROGRAMS $<TARGET_FILE:${GO_LIBNAME}_shared> ${INSTALL_IS_OPTIONAL}
TYPE LIB)
endif()
else()
install(IMPORTED_RUNTIME_ARTIFACTS
${GO_LIBNAME}_shared
${INSTALL_IS_OPTIONAL}
RUNTIME
DESTINATION
${RUNTIME_INSTALL_DIR}
LIBRARY
DESTINATION
${CMAKE_INSTALL_LIBDIR})
endif()
if(WIN32)
# This symlink doesn't get installed
install(FILES "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" TYPE BIN)
else()
install(FILES "${LIBOUT_SHARED}" "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" TYPE LIB)
endif()
endif()
if(BUILD_STATIC)
set(LIBNAME_STATIC
"${CMAKE_STATIC_LIBRARY_PREFIX}${GO_LIBNAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(LIBOUT_STATIC "${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME_STATIC}")
if(CMAKE_VERSION VERSION_LESS "3.20")
string(REGEX REPLACE "\\..+$" ".h" LIBOUT_HEADER "${LIBOUT_STATIC}")
else()
cmake_path(REPLACE_EXTENSION
LIBOUT_STATIC
".h"
OUTPUT_VARIABLE
LIBOUT_HEADER)
endif()
add_custom_command(OUTPUT "${LIBOUT_STATIC}"
WORKING_DIRECTORY ${GO_MOD_DIR}
DEPENDS ${ARG_SOURCES}
COMMAND ${CMAKE_COMMAND} -E env "${GO_ENV_VARS}" ${GO_BIN} build
"${GO_BUILD_TAGS}" -o "${LIBOUT_STATIC}"
-buildmode=c-archive "${GO_BUILD_FLAGS}" .
COMMAND ${CMAKE_COMMAND} -E remove -f "${LIBOUT_HEADER}"
COMMENT "Building Go Static lib ${GO_LIBNAME}"
COMMAND_EXPAND_LISTS)
add_custom_target(${GO_LIBNAME}_static_target ALL DEPENDS "${LIBOUT_STATIC}")
add_library(${GO_LIBNAME}_static STATIC IMPORTED)
set_target_properties(${GO_LIBNAME}_static PROPERTIES IMPORTED_LOCATION
"${LIBOUT_STATIC}")
add_dependencies(${GO_LIBNAME}_static ${GO_LIBNAME}_static_target)
if(ARG_OUTPUTS)
list(APPEND ${ARG_OUTPUTS} ${GO_LIBNAME}_static)
endif()
install(FILES "${LIBOUT_STATIC}" TYPE LIB)
endif()
if(ARG_PKG_CONFIG_NAME)
arrow_add_pkg_config("${ARG_PKG_CONFIG_NAME}")
endif()
# Modify variable in calling scope
if(ARG_OUTPUTS)
set(${ARG_OUTPUTS}
${${ARG_OUTPUTS}}
PARENT_SCOPE)
endif()
endfunction()