## ## Copyright (C) The Software Authors. All rights reserved. ## Use of this source code is governed by a BSD-style ## license that can be found in the LICENSE file. ## ## \file bazel.cmake ## \author Yunfeng.Xiao ## \date Apr 7, 2021 ## \version 1.2.13 ## \brief Detail cmake bazel framework build script ## ## ## The following functions used by user's CMakeLists.txt: ## ## 1. Functions for C/C++ ## ## 1.1. Add a subdirectory to the build ## cc_directory( [binary_dir]) ## ## 1.2. Add subdirectories to the build ## cc_directories( [source_dir2 ...]) ## ## 1.3. Build a C/C++ static or shared library ## cc_library( ## NAME ## [STATIC] [SHARED] [STRICT] [ALWAYS_LINK] [EXCLUDE] [PACKED] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [PUBINCS public_dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [PACKED_EXCLUDES pattern1 ...] ## [VERSION ] ## ) ## ## 1.4. Build a C/C++ executable program ## cc_binary( ## NAME ## [STRICT] [PACKED] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [VERSION ] ## ) ## ## 1.5. Build a C/C++ executable test program ## cc_test( ## NAME ## [STRICT] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [ARGS args1 ...] ## [VERSION ] ## ) ## ## 1.6. Add existing test cases to a test suite ## cc_test_suite( [test_name ...]) ## ## 1.7. Import a C/C++ static or shared library ## cc_import( ## NAME ## [STATIC | SHARED] [PACKED] ## PATH ## [INCS dir1 ...] ## [PUBINCS public_dir1 ...] ## [DEPS target1 ...] ## [IMPLIB ] ## [PACKED_EXCLUDES pattern1 ...] ## ) ## ## 1.8. Import a C/C++ interface library ## cc_interface( ## NAME ## [PACKED] ## [INCS dir1 ...] ## [PUBINCS public_dir1 ...] ## [DEPS target1 ...] ## [PACKED_EXCLUDES pattern1 ...] ## ) ## ## 1.9. Build a C/C++ executable google test program ## cc_gtest( ## NAME ## [STRICT] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [ARGS args1 ...] ## [VERSION ] ## ) ## ## 1.10. Build a C/C++ executable google mock program ## cc_gmock( ## NAME ## [STRICT] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [ARGS args1 ...] ## [VERSION ] ## ) ## ## 1.11. Build a C++ protobuf static or shared library ## cc_proto_library( ## NAME ## [STATIC] [SHARED] [STRICT] [EXCLUDE] [PACKED] ## SRCS [file2.proto ...] ## [PROTOROOT path] ## [CXXFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [VERSION ] ## [PROTOBUF_VERSION ] ## ) ## ## 2. Functions for CUDA ## ## 2.1. Add a subdirectory to the build ## cuda_directory( [binary_dir]) ## ## 2.2. Add subdirectories to the build ## cuda_directories( [source_dir2 ...]) ## ## 2.3. Build a CUDA static or shared library ## cuda_library( ## NAME ## [STATIC] [SHARED] [STRICT] [ALWAYS_LINK] [EXCLUDE] [PACKED] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [PUBINCS public_dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [CUDAFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [PACKED_EXCLUDES pattern1 ...] ## [VERSION ] ## ) ## ## 2.4. Build a CUDA executable program ## cuda_binary( ## NAME ## [STRICT] [PACKED] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [CUDAFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [VERSION ] ## ) ## ## 2.5. Build a CUDA executable test program ## cuda_test( ## NAME ## [STRICT] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [CUDAFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [ARGS args1 ...] ## [VERSION ] ## ) ## ## 2.6. Add existing test cases to a test suite ## cuda_test_suite( [test_name ...]) ## ## 2.7. Import a C/C++/CUDA static or shared library ## cuda_import( ## NAME ## [STATIC | SHARED] [PACKED] ## PATH ## [INCS dir1 ...] ## [PUBINCS public_dir1 ...] ## [DEPS target1 ...] ## [IMPLIB ] ## [PACKED_EXCLUDES pattern1 ...] ## ) ## ## 2.8. Import a C/C++/CUDA interface library ## cuda_interface( ## NAME ## [PACKED] ## [INCS dir1 ...] ## [PUBINCS public_dir1 ...] ## [DEPS target1 ...] ## [PACKED_EXCLUDES pattern1 ...] ## ) ## ## 2.9. Build a CUDA executable google test program ## cuda_gtest( ## NAME ## [STRICT] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [CUDAFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [ARGS args1 ...] ## [VERSION ] ## ) ## ## 2.10. Build a CUDA executable google mock program ## cuda_gmock( ## NAME ## [STRICT] ## SRCS [file2 ...] ## [INCS dir1 ...] ## [DEFS DEF1=1 ...] ## [LIBS lib1 ...] ## [CFLAGS flag1 ...] ## [CXXFLAGS flag1 ...] ## [CUDAFLAGS flag1 ...] ## [LDFLAGS flag1 ...] ## [DEPS target1 ...] ## [ARGS args1 ...] ## [VERSION ] ## ) ## ## 3. Utility functions ## ## 3.1. Download a git repository ## git_repository( ## NAME ## URL ## [TAG ] ## [PATH ] ## ) ## ## 3.2. Download a hg repository ## hg_repository( ## NAME ## URL ## [TAG ] ## [PATH ] ## ) ## ## 3.3. Download a svn repository ## svn_repository( ## NAME ## URL ## [REV ] ## [PATH ] ## ) ## ## 3.4. Download a http archive ## http_archive( ## NAME ## URL ## [SHA256 | SHA1 | MD5 ] ## [PATH ] ## ) ## ## 3.5. Retrieve a version string from GIT ## git_version( ## ## ## ) ## ## 3.6. Retrieve a version string from HG ## hg_version( ## ## ## ) ## ## 3.7. Retrieve a version string from SVN ## svn_version( ## ## ## ) ## cmake_minimum_required(VERSION 3.1 FATAL_ERROR) include(CMakeParseArguments) # Using AppleClang instead of Clang (Compiler id) if(POLICY CMP0025) cmake_policy(SET CMP0025 NEW) endif() # Enable unit testing enable_testing() # Add unittest target if(NOT TARGET unittest) add_custom_target( unittest COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --build-config $ ) endif() # Directories of target output if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) endif() if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) endif() if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) endif() # RPATH settings set(CMAKE_MACOSX_RPATH ON) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_SKIP_BUILD_RPATH ON) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) if(${CMAKE_SIZEOF_VOID_P} EQUAL "8") set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib64:$ORIGIN/../lib:$ORIGIN") else() set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN") endif() else() set(CMAKE_INSTALL_RPATH "@loader_path/../lib:@loader_path") endif() # Define standard installation directories if(NOT CMAKE_INSTALL_LIBDIR) set(CMAKE_INSTALL_LIBDIR lib) endif() if(NOT CMAKE_INSTALL_BINDIR) set(CMAKE_INSTALL_BINDIR bin) endif() if(NOT CMAKE_INSTALL_INCDIR) set(CMAKE_INSTALL_INCDIR include) endif() if(NOT CMAKE_INSTALL_ETCDIR) set(CMAKE_INSTALL_ETCDIR etc) endif() # Generates a compile_commands.json set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) if(NOT MSVC) # Use color in diagnostics set( _COMPILER_FLAGS "$<$:-fcolor-diagnostics>" "$<$:-fcolor-diagnostics>" "$<$:-fdiagnostics-color=always>" ) add_compile_options( "$<$:${_COMPILER_FLAGS}>" "$<$:${_COMPILER_FLAGS}>" ) unset(_COMPILER_FLAGS) else() # Replace the default compiling flags set( _COMPILER_FLAGS CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL ) foreach(COMPILER_FLAG ${_COMPILER_FLAGS}) string(REPLACE "/MT" "/MD" ${COMPILER_FLAG} "${${COMPILER_FLAG}}") string(REGEX REPLACE "/W[0-9]" "" ${COMPILER_FLAG} "${${COMPILER_FLAG}}") endforeach() unset(_COMPILER_FLAGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Build shared library as default set(BUILD_SHARED_LIBS ON) endif() set(CMAKE_C_FLAGS_ASAN ${CMAKE_C_FLAGS_DEBUG}) set(CMAKE_CXX_FLAGS_ASAN ${CMAKE_CXX_FLAGS_DEBUG}) set(CMAKE_EXE_LINKER_FLAGS_ASAN ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) set(CMAKE_SHARED_LINKER_FLAGS_ASAN ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}) set(CMAKE_STATIC_LINKER_FLAGS_ASAN ${CMAKE_STATIC_LINKER_FLAGS_DEBUG}) set(CMAKE_MODULE_LINKER_FLAGS_ASAN ${CMAKE_MODULE_LINKER_FLAGS_DEBUG}) set(CMAKE_C_FLAGS_COVERAGE ${CMAKE_C_FLAGS_DEBUG}) set(CMAKE_CXX_FLAGS_COVERAGE ${CMAKE_CXX_FLAGS_DEBUG}) set(CMAKE_EXE_LINKER_FLAGS_COVERAGE ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}) set(CMAKE_STATIC_LINKER_FLAGS_COVERAGE ${CMAKE_STATIC_LINKER_FLAGS_DEBUG}) set(CMAKE_MODULE_LINKER_FLAGS_COVERAGE ${CMAKE_MODULE_LINKER_FLAGS_DEBUG}) # C/C++ ASAN compile flags set( BAZEL_CC_ASAN_COMPILE_FLAGS "$<$:$<$:-fsanitize=address>>" "$<$:$<$:-fsanitize=address>>" "$<$:$<$:-fsanitize=address>>" "$<$:$<$:/fsanitize=address>>" ) # C/C++ COVERAGE compile flags set( BAZEL_CC_COVERAGE_COMPILE_FLAGS "$<$:$<$:--coverage>>" "$<$:$<$:--coverage>>" "$<$:$<$:--coverage>>" ) # C/C++ strict compile flags set( BAZEL_CC_STRICT_COMPILE_FLAGS "$<$:-Wall;-Wextra;-Wshadow>" "$<$:-Wall;-Wextra;-Wshadow>" "$<$:-Wall;-Wextra;-Wshadow>" "$<$:/W4>" ${BAZEL_CC_ASAN_COMPILE_FLAGS} ${BAZEL_CC_COVERAGE_COMPILE_FLAGS} ) # C/C++ strict link flags set( BAZEL_CC_STRICT_LINK_FLAGS ${BAZEL_CC_ASAN_COMPILE_FLAGS} ${BAZEL_CC_COVERAGE_COMPILE_FLAGS} ) # C/C++ unstrict compile flags set( BAZEL_CC_UNSTRICT_COMPILE_FLAGS "$<$:-Wall>" "$<$:-Wall>" "$<$:-Wall>" "$<$:/W3>" ${BAZEL_CC_ASAN_COMPILE_FLAGS} ${BAZEL_CC_COVERAGE_COMPILE_FLAGS} ) # C/C++ unstrict link flags set( BAZEL_CC_UNSTRICT_LINK_FLAGS ${BAZEL_CC_ASAN_COMPILE_FLAGS} ${BAZEL_CC_COVERAGE_COMPILE_FLAGS} ) # CUDA strict compile flags set( BAZEL_CUDA_STRICT_COMPILE_FLAGS "$<$:$<$:-Wall;-Wextra;-Wshadow>>" "$<$:$<$:-Wall;-Wextra;-Wshadow>>" "$<$:$<$:-Wall;-Wextra;-Wshadow>>" "$<$:$<$:/W4>>" "$<$:$<$:-Wall;-Wextra;-Wshadow>>" "$<$:$<$:-Wall;-Wextra;-Wshadow>>" "$<$:$<$:-Wall;-Wextra;-Wshadow>>" "$<$:$<$:/W4>>" "$<$:$<$:-G>>" ) # CUDA strict link flags set(BAZEL_CUDA_STRICT_LINK_FLAGS "") # CUDA unstrict compile flags set( BAZEL_CUDA_UNSTRICT_COMPILE_FLAGS "$<$:$<$:-Wall>>" "$<$:$<$:-Wall>>" "$<$:$<$:-Wall>>" "$<$:$<$:/W3>>" "$<$:$<$:-Wall>>" "$<$:$<$:-Wall>>" "$<$:$<$:-Wall>>" "$<$:$<$:/W3>>" "$<$:$<$:-G>>" ) # CUDA unstrict link flags set(BAZEL_CUDA_UNSTRICT_LINK_FLAGS "") ## Find workspace directory function(_find_workspace_directory _RESULT) # Find Workspace.cmake folder set(_CURRENT_WORKSPACE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) get_filename_component( _PARENT_WORKSPACE_DIR ${_CURRENT_WORKSPACE_DIR} DIRECTORY ) while(NOT ("${_CURRENT_WORKSPACE_DIR}" STREQUAL "${_PARENT_WORKSPACE_DIR}")) if(EXISTS "${_CURRENT_WORKSPACE_DIR}/Workspace.cmake") set(${_RESULT} ${_CURRENT_WORKSPACE_DIR} PARENT_SCOPE) message(STATUS "Found workspace at ${${_RESULT}}") break() endif() # Find next parent folder set(_CURRENT_WORKSPACE_DIR ${_PARENT_WORKSPACE_DIR}) get_filename_component( _PARENT_WORKSPACE_DIR ${_CURRENT_WORKSPACE_DIR} DIRECTORY ) endwhile() endfunction() ## Retrieve absolute paths function(_absolute_paths _RESULT) foreach(FILEPATH ${ARGN}) if(NOT IS_ABSOLUTE ${FILEPATH}) get_filename_component(FILEPATH ${FILEPATH} ABSOLUTE) endif() list(APPEND FILEPATHS ${FILEPATH}) endforeach() set(${_RESULT} "${FILEPATHS}" PARENT_SCOPE) endfunction() ## Add both shared and static library macro(_add_library _NAME _OPTION) add_library(${_NAME}_objects OBJECT ${_OPTION} ${ARGN}) add_library( ${_NAME}_static STATIC ${_OPTION} $ ) add_library( ${_NAME} SHARED ${_OPTION} $ ) add_dependencies(${_NAME} ${_NAME}_static) if(NOT MSVC) set_property(TARGET ${_NAME}_static PROPERTY OUTPUT_NAME ${_NAME}) endif() endmacro() ## Link dependencies function(_targets_link_dependencies _NAME) foreach(LIB ${ARGN}) if(TARGET ${LIB}) list(APPEND LIBS_DEPS ${LIB}) list( APPEND LIBS_INCS "$" ) endif() endforeach() if(LIBS_DEPS) add_dependencies(${_NAME} ${LIBS_DEPS}) target_include_directories(${_NAME} PRIVATE "${LIBS_INCS}") endif() endfunction() ## Link libraries function(_target_link_libraries _NAME) foreach(LIB ${ARGN}) if(NOT TARGET ${LIB}) list(APPEND LINK_LIBS ${LIB}) continue() endif() get_target_property(ALWAYS_LINK ${LIB} ALWAYS_LINK) if(NOT ALWAYS_LINK) list(APPEND LINK_LIBS ${LIB}) continue() endif() if(NOT MSVC) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") list(APPEND LINK_LIBS -Wl,--whole-archive ${LIB} -Wl,--no-whole-archive) else() list(APPEND LINK_LIBS -Wl,-force_load ${LIB}) endif() else() # Microsoft Visual C++ list(APPEND LINK_LIBS /WHOLEARCHIVE:$) get_target_property(OTHER_LINK_LIBS ${LIB} INTERFACE_LINK_LIBRARIES) if(OTHER_LINK_LIBS) list(APPEND LINK_LIBS ${OTHER_LINK_LIBS}) endif() list(APPEND LIBS_DEPS ${LIB}) list( APPEND LIBS_INCS "$" ) endif() endforeach() target_link_libraries(${_NAME} ${LINK_LIBS}) if(LIBS_DEPS) add_dependencies(${_NAME} ${LIBS_DEPS}) target_include_directories(${_NAME} PRIVATE "${LIBS_INCS}") endif() endfunction() ## Add a subdirectory to the build function(cc_directory) add_subdirectory(${ARGN}) endfunction() ## Add subdirectories to the build function(cc_directories) foreach(SRC_DIR ${ARGN}) add_subdirectory(${SRC_DIR}) endforeach() endfunction() ## Set the properties of target function(_cc_target_properties) cmake_parse_arguments( CC_ARGS "STRICT;ALWAYS_LINK" "NAME;VERSION;C_STANDARD;CXX_STANDARD" "INCS;PUBINCS;DEFS;LIBS;CFLAGS;CXXFLAGS;LDFLAGS;DEPS" ${ARGN} ) if(NOT CC_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() get_target_property(TARGET_TYPE ${CC_ARGS_NAME} TYPE) if(("${TARGET_TYPE}" STREQUAL "SHARED_LIBRARY") OR ("${TARGET_TYPE}" STREQUAL "STATIC_LIBRARY") OR ("${TARGET_TYPE}" STREQUAL "EXECUTABLE")) set(TARGET_LINKABLE TRUE) endif() if(CC_ARGS_ALWAYS_LINK) if(("${TARGET_TYPE}" STREQUAL "STATIC_LIBRARY") OR ("${TARGET_TYPE}" STREQUAL "OBJECT_LIBRARY")) set_property(TARGET ${CC_ARGS_NAME} PROPERTY ALWAYS_LINK TRUE) endif() endif() # Set the warning level of compiling if(CC_ARGS_STRICT) target_compile_options( ${CC_ARGS_NAME} PRIVATE "${BAZEL_CC_STRICT_COMPILE_FLAGS}" ) if(TARGET_LINKABLE) target_link_libraries(${CC_ARGS_NAME} "${BAZEL_CC_STRICT_LINK_FLAGS}") endif() else() target_compile_options( ${CC_ARGS_NAME} PRIVATE "${BAZEL_CC_UNSTRICT_COMPILE_FLAGS}" ) if(TARGET_LINKABLE) target_link_libraries(${CC_ARGS_NAME} "${BAZEL_CC_UNSTRICT_LINK_FLAGS}") endif() endif() if(CC_ARGS_DEFS) target_compile_definitions(${CC_ARGS_NAME} PRIVATE "${CC_ARGS_DEFS}") endif() if(CC_ARGS_CFLAGS OR CC_ARGS_CXXFLAGS) target_compile_options( ${CC_ARGS_NAME} PRIVATE "$<$:${CC_ARGS_CFLAGS}>" "$<$:${CC_ARGS_CXXFLAGS}>" ) endif() if(CC_ARGS_LDFLAGS) string(REPLACE ";" " " CC_ARGS_LDFLAGS "${CC_ARGS_LDFLAGS}") set_property( TARGET ${CC_ARGS_NAME} PROPERTY LINK_FLAGS "${CC_ARGS_LDFLAGS}" ) endif() if(CC_ARGS_INCS) _absolute_paths(INC_DIRS ${CC_ARGS_INCS}) target_include_directories(${CC_ARGS_NAME} PRIVATE "${INC_DIRS}") endif() if(BAZEL_WORKSPACE_DIR) target_include_directories(${CC_ARGS_NAME} PRIVATE "${BAZEL_WORKSPACE_DIR}") endif() if(CC_ARGS_PUBINCS) _absolute_paths(INC_DIRS ${CC_ARGS_PUBINCS}) target_include_directories(${CC_ARGS_NAME} PUBLIC "${INC_DIRS}") endif() if(CC_ARGS_LIBS) if(NOT TARGET_LINKABLE) _targets_link_dependencies(${CC_ARGS_NAME} ${CC_ARGS_LIBS}) else() if ("${TARGET_TYPE}" STREQUAL "EXECUTABLE") _target_link_libraries(${CC_ARGS_NAME} "${CC_ARGS_LIBS}") else() target_link_libraries(${CC_ARGS_NAME} "${CC_ARGS_LIBS}") endif() endif() endif() if(CC_ARGS_DEPS) add_dependencies(${CC_ARGS_NAME} "${CC_ARGS_DEPS}") endif() if(CC_ARGS_VERSION) set_property( TARGET ${CC_ARGS_NAME} PROPERTY VERSION "${CC_ARGS_VERSION}" ) endif() if(NOT CC_C_STANDARD) set(CC_C_STANDARD 99) endif() if(NOT CC_CXX_STANDARD) set(CC_CXX_STANDARD 11) endif() set_target_properties( ${CC_ARGS_NAME} PROPERTIES DEFINE_SYMBOL "" C_STANDARD ${CC_C_STANDARD} CXX_STANDARD ${CC_CXX_STANDARD} C_STANDARD_REQUIRED ON C_EXTENSIONS ON CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF WINDOWS_EXPORT_ALL_SYMBOLS ON ) endfunction() ## Build a C/C++ static or shared library function(cc_library) cmake_parse_arguments( CC_ARGS "STATIC;SHARED;EXCLUDE;PACKED" "NAME;VERSION" "SRCS;INCS;PUBINCS;DEFS;LIBS;CFLAGS;CXXFLAGS;LDFLAGS;DEPS;PACKED_EXCLUDES" ${ARGN} ) if(NOT CC_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CC_ARGS_SRCS ${CC_ARGS_SRCS}) if(NOT CC_ARGS_SRCS) message(FATAL_ERROR "No source files found of ${CC_ARGS_NAME}.") endif() if(CC_ARGS_VERSION) string(REPLACE "-" "_" MACRO_PREFIX "${CC_ARGS_NAME}") list(APPEND CC_ARGS_DEFS ${MACRO_PREFIX}_VERSION="${CC_ARGS_VERSION}") endif() if(CC_ARGS_EXCLUDE) set(EXCLUDE_OPTION EXCLUDE_FROM_ALL) endif() if(CC_ARGS_SHARED AND CC_ARGS_STATIC) _add_library(${CC_ARGS_NAME} "${EXCLUDE_OPTION}" "${CC_ARGS_SRCS}") elseif(CC_ARGS_SHARED) add_library(${CC_ARGS_NAME} SHARED ${EXCLUDE_OPTION} ${CC_ARGS_SRCS}) elseif(CC_ARGS_STATIC) add_library(${CC_ARGS_NAME} STATIC ${EXCLUDE_OPTION} ${CC_ARGS_SRCS}) else() add_library(${CC_ARGS_NAME} ${EXCLUDE_OPTION} ${CC_ARGS_SRCS}) endif() if(TARGET ${CC_ARGS_NAME}_objects) _cc_target_properties( NAME "${CC_ARGS_NAME}_objects" INCS "${CC_ARGS_INCS};${CC_ARGS_PUBINCS}" DEFS "${CC_ARGS_DEFS}" LIBS "${CC_ARGS_LIBS}" CFLAGS "${CC_ARGS_CFLAGS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) endif() if(TARGET ${CC_ARGS_NAME}_static) _cc_target_properties( NAME "${CC_ARGS_NAME}_static" INCS "${CC_ARGS_INCS}" PUBINCS "${CC_ARGS_PUBINCS}" DEFS "${CC_ARGS_DEFS}" LIBS "${CC_ARGS_LIBS}" CFLAGS "${CC_ARGS_CFLAGS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) if(CC_ARGS_PACKED) install( TARGETS ${CC_ARGS_NAME}_static ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) endif() endif() _cc_target_properties( NAME "${CC_ARGS_NAME}" INCS "${CC_ARGS_INCS}" PUBINCS "${CC_ARGS_PUBINCS}" DEFS "${CC_ARGS_DEFS}" LIBS "${CC_ARGS_LIBS}" CFLAGS "${CC_ARGS_CFLAGS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" VERSION "${CC_ARGS_VERSION}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) if(CC_ARGS_PACKED) install( TARGETS ${CC_ARGS_NAME} ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) if(CC_ARGS_PUBINCS) foreach(PACKED_EXCLUDE ${CC_ARGS_PACKED_EXCLUDES}) list(APPEND PATTERN_EXCLUDES "PATTERN;${PACKED_EXCLUDE};EXCLUDE") endforeach() install( DIRECTORY ${CC_ARGS_PUBINCS} DESTINATION ${CMAKE_INSTALL_INCDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.hxx" ${PATTERN_EXCLUDES} ) endif() endif() endfunction() ## Build a C/C++ executable program function(cc_binary) cmake_parse_arguments( CC_ARGS "PACKED" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;LDFLAGS;DEPS" ${ARGN} ) if(NOT CC_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CC_ARGS_SRCS ${CC_ARGS_SRCS}) if(NOT CC_ARGS_SRCS) message(FATAL_ERROR "No source files found of ${CC_ARGS_NAME}.") endif() if(CC_ARGS_VERSION) string(REPLACE "-" "_" MACRO_PREFIX "${CC_ARGS_NAME}") list(APPEND CC_ARGS_DEFS ${MACRO_PREFIX}_VERSION="${CC_ARGS_VERSION}") endif() add_executable(${CC_ARGS_NAME} ${CC_ARGS_SRCS}) if(CC_ARGS_PACKED) install( TARGETS ${CC_ARGS_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) endif() _cc_target_properties( NAME "${CC_ARGS_NAME}" INCS "${CC_ARGS_INCS}" DEFS "${CC_ARGS_DEFS}" LIBS "${CC_ARGS_LIBS}" CFLAGS "${CC_ARGS_CFLAGS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" VERSION "${CC_ARGS_VERSION}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) endfunction() ## Build a C/C++ executable test program function(cc_test) cmake_parse_arguments( CC_ARGS "" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;LDFLAGS;DEPS;ARGS" ${ARGN} ) if(NOT CC_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CC_ARGS_SRCS ${CC_ARGS_SRCS}) if(NOT CC_ARGS_SRCS) message(FATAL_ERROR "No source files found of ${CC_ARGS_NAME}.") endif() if(CC_ARGS_VERSION) string(REPLACE "-" "_" MACRO_PREFIX "${CC_ARGS_NAME}") list(APPEND CC_ARGS_DEFS ${MACRO_PREFIX}_VERSION="${CC_ARGS_VERSION}") endif() add_executable(${CC_ARGS_NAME} EXCLUDE_FROM_ALL ${CC_ARGS_SRCS}) _cc_target_properties( NAME "${CC_ARGS_NAME}" INCS "${CC_ARGS_INCS}" DEFS "${CC_ARGS_DEFS}" LIBS "${CC_ARGS_LIBS}" CFLAGS "${CC_ARGS_CFLAGS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) add_dependencies(unittest ${CC_ARGS_NAME}) add_custom_target( unittest.${CC_ARGS_NAME} COMMAND $ "${CC_ARGS_ARGS}" WORKING_DIRECTORY ${PROJECT_BINARY_DIR} DEPENDS ${CC_ARGS_NAME} ) add_test( NAME ${CC_ARGS_NAME} COMMAND $ "${CC_ARGS_ARGS}" WORKING_DIRECTORY ${PROJECT_BINARY_DIR} ) endfunction() ## Add existing test cases to a test suite function(cc_test_suite _NAME) if(NOT TARGET unittest.${_NAME}) add_custom_target(unittest.${_NAME} COMMAND "") endif() foreach(TEST_TARGET ${ARGN}) list(APPEND TEST_TARGETS unittest.${TEST_TARGET}) endforeach() if(TEST_TARGETS) add_dependencies(unittest.${_NAME} ${TEST_TARGETS}) endif() endfunction() ## Import a C/C++ static or shared library function(cc_import) cmake_parse_arguments( CC_ARGS "STATIC;SHARED;PACKED" "NAME;PATH;IMPLIB" "INCS;PUBINCS;DEPS;PACKED_EXCLUDES" ${ARGN} ) if(NOT CC_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CC_ARGS_PATH ${CC_ARGS_PATH}) if(NOT CC_ARGS_PATH) message(FATAL_ERROR "No imported target file found of ${CC_ARGS_NAME}.") endif() if(MSVC AND CC_ARGS_SHARED AND NOT CC_ARGS_IMPLIB) string(REGEX REPLACE ".[Dd][Ll][Ll]$" ".lib" CC_ARGS_IMPLIB ${CC_ARGS_PATH} ) endif() if(CC_ARGS_SHARED) add_library(${CC_ARGS_NAME} SHARED IMPORTED GLOBAL) elseif(CC_ARGS_STATIC) add_library(${CC_ARGS_NAME} STATIC IMPORTED GLOBAL) else() add_library(${CC_ARGS_NAME} UNKNOWN IMPORTED GLOBAL) endif() set_property( TARGET ${CC_ARGS_NAME} PROPERTY IMPORTED_LOCATION ${CC_ARGS_PATH} ) if(MSVC AND CC_ARGS_SHARED) set_property( TARGET ${CC_ARGS_NAME} PROPERTY IMPORTED_IMPLIB ${CC_ARGS_IMPLIB} ) endif() if(CC_ARGS_INCS) _absolute_paths(INC_DIRS ${CC_ARGS_INCS}) foreach(INC_DIR ${INC_DIRS}) set_property( TARGET ${CC_ARGS_NAME} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${INC_DIR}" ) endforeach() endif() if(CC_ARGS_PUBINCS) _absolute_paths(INC_DIRS ${CC_ARGS_PUBINCS}) foreach(INC_DIR ${INC_DIRS}) set_property( TARGET ${CC_ARGS_NAME} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${INC_DIR}" ) endforeach() endif() if(CC_ARGS_DEPS) add_dependencies(${CC_ARGS_NAME} "${CC_ARGS_DEPS}") endif() if(CC_ARGS_PACKED) install( TARGETS ${CC_ARGS_NAME} ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) if(CC_ARGS_PUBINCS) foreach(PACKED_EXCLUDE ${CC_ARGS_PACKED_EXCLUDES}) list(APPEND PATTERN_EXCLUDES "PATTERN;${PACKED_EXCLUDE};EXCLUDE") endforeach() install( DIRECTORY ${CC_ARGS_PUBINCS} DESTINATION ${CMAKE_INSTALL_INCDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.hxx" ${PATTERN_EXCLUDES} ) endif() endif() endfunction() ## Import a C/C++ interface library function(cc_interface) cmake_parse_arguments( CC_ARGS "PACKED" "NAME" "INCS;PUBINCS;DEPS;PACKED_EXCLUDES" ${ARGN} ) if(NOT CC_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() add_library(${CC_ARGS_NAME} INTERFACE GLOBAL) if(CC_ARGS_INCS) _absolute_paths(INC_DIRS ${CC_ARGS_INCS}) target_include_directories(${CC_ARGS_NAME} INTERFACE "${INC_DIRS}") endif() if(CC_ARGS_PUBINCS) _absolute_paths(INC_DIRS ${CC_ARGS_PUBINCS}) target_include_directories(${CC_ARGS_NAME} INTERFACE "${INC_DIRS}") endif() if(CC_ARGS_DEPS) add_dependencies(${CC_ARGS_NAME} "${CC_ARGS_DEPS}") endif() if(CC_ARGS_PACKED AND CC_ARGS_PUBINCS) foreach(PACKED_EXCLUDE ${CC_ARGS_PACKED_EXCLUDES}) list(APPEND PATTERN_EXCLUDES "PATTERN;${PACKED_EXCLUDE};EXCLUDE") endforeach() install( DIRECTORY ${CC_ARGS_PUBINCS} DESTINATION ${CMAKE_INSTALL_INCDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.hxx" ${PATTERN_EXCLUDES} ) endif() endfunction() ## Find gtest library function(_find_gtest) if(DEFINED FIND_GTEST_LIBS AND DEFINED FIND_GTEST_INCS) return() endif() if(NOT TARGET gtest OR NOT TARGET gtest_main) # Find gtest using 'find_package' find_package(GTest REQUIRED) set( FIND_GTEST_INCS "${GTEST_INCLUDE_DIRS}" CACHE STRING "GTest includes" ) set( FIND_GTEST_LIBS "${GTEST_BOTH_LIBRARIES}" CACHE STRING "GTest libraries" ) else() # Find gtest using target names set(FIND_GTEST_INCS "" CACHE STRING "GTest includes") set(FIND_GTEST_LIBS "gtest;gtest_main" CACHE STRING "GTest libraries") endif() endfunction() ## Build a C/C++ executable google test program function(cc_gtest) cmake_parse_arguments( CC_ARGS "" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;LDFLAGS;DEPS;ARGS" ${ARGN} ) _find_gtest() cc_test( NAME "${CC_ARGS_NAME}" VERSION "${CC_ARGS_VERSION}" SRCS "${CC_ARGS_SRCS}" INCS "${CC_ARGS_INCS};${FIND_GTEST_INCS}" DEFS "${CC_ARGS_DEFS}" LIBS "${CC_ARGS_LIBS};${FIND_GTEST_LIBS}" CFLAGS "${CC_ARGS_CFLAGS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" ARGS "${CC_ARGS_ARGS}" ) endfunction() ## Find gmock library function(_find_gmock) if(DEFINED FIND_GMOCK_LIBS AND DEFINED FIND_GMOCK_INCS) return() endif() if(NOT TARGET gmock OR NOT TARGET gmock_main) # Find gmock/gtest using 'find_package' find_package(GMock REQUIRED) find_package(GTest REQUIRED) set( FIND_GMOCK_INCS "${GMOCK_INCLUDE_DIRS};${GTEST_INCLUDE_DIRS}" CACHE STRING "GMock includes" ) set( FIND_GMOCK_LIBS "${GMOCK_BOTH_LIBRARIES};${GTEST_LIBRARIES}" CACHE STRING "GMock libraries" ) else() # Find gmock using target names set(FIND_GMOCK_INCS "" CACHE STRING "GMock includes") set(FIND_GMOCK_LIBS "gmock;gmock_main" CACHE STRING "GMock libraries") endif() endfunction() ## Build a C/C++ executable google mock program function(cc_gmock) cmake_parse_arguments( CC_ARGS "" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;LDFLAGS;DEPS;ARGS" ${ARGN} ) _find_gmock() cc_test( NAME "${CC_ARGS_NAME}" VERSION "${CC_ARGS_VERSION}" SRCS "${CC_ARGS_SRCS}" INCS "${CC_ARGS_INCS};${FIND_GMOCK_INCS}" DEFS "${CC_ARGS_DEFS}" LIBS "${CC_ARGS_LIBS};${FIND_GMOCK_LIBS}" CFLAGS "${CC_ARGS_CFLAGS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" ARGS "${CC_ARGS_ARGS}" ) endfunction() ## Find protobuf library function(_find_protobuf _VERSION) if(DEFINED CC_PROTOBUF_PROTOC_${_VERSION}) return() endif() # Find protobuf using 'find_package' if(NOT TARGET protoc OR NOT TARGET libprotobuf) find_package(Protobuf ${_VERSION} REQUIRED) set( CC_PROTOBUF_PROTOC_${_VERSION} "${PROTOBUF_PROTOC_EXECUTABLE}" CACHE PATH "Protobuf compiler" ) set( CC_PROTOBUF_INCS_${_VERSION} "${PROTOBUF_INCLUDE_DIRS}" CACHE STRING "Protobuf includes" ) set( CC_PROTOBUF_LIBS_${_VERSION} "${PROTOBUF_LIBRARIES}" CACHE STRING "Protobuf libraries" ) return() endif() # Find protobuf using target names get_target_property(protoc_VERSION protoc VERSION) get_target_property(libprotobuf_VERSION libprotobuf VERSION) if(_VERSION) if(${protoc_VERSION} VERSION_LESS ${_VERSION}) message( FATAL_ERROR "The 'protoc' version is ${protoc_VERSION}, less than ${_VERSION}." ) endif() if(${libprotobuf_VERSION} VERSION_LESS ${_VERSION}) message( FATAL_ERROR "The 'libprotobuf' version is ${libprotobuf_VERSION}, " "less than ${_VERSION}." ) endif() endif() message(STATUS "Found binary 'protoc ${protoc_VERSION}'") message(STATUS "Found library 'libprotobuf ${libprotobuf_VERSION}'") set( CC_PROTOBUF_PROTOC_${_VERSION} "$" CACHE PATH "Protobuf compiler" ) set( CC_PROTOBUF_INCS_${_VERSION} "" CACHE STRING "Protobuf includes" ) set( CC_PROTOBUF_LIBS_${_VERSION} libprotobuf CACHE STRING "Protobuf libraries" ) endfunction() ## Build a C++ protobuf static or shared library function(cc_proto_library) cmake_parse_arguments( CC_ARGS "STATIC;SHARED;EXCLUDE;PACKED" "NAME;VERSION;PROTOROOT;PROTOBUF_VERSION" "SRCS;CXXFLAGS;LDFLAGS;DEPS" ${ARGN} ) _find_protobuf("${CC_ARGS_PROTOBUF_VERSION}") set(CC_PROTOBUF_PROTOC ${CC_PROTOBUF_PROTOC_${CC_ARGS_PROTOBUF_VERSION}}) set(CC_PROTOBUF_INCS ${CC_PROTOBUF_INCS_${CC_ARGS_PROTOBUF_VERSION}}) set(CC_PROTOBUF_LIBS ${CC_PROTOBUF_LIBS_${CC_ARGS_PROTOBUF_VERSION}}) if(NOT CC_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CC_ARGS_SRCS ${CC_ARGS_SRCS}) if(NOT CC_ARGS_SRCS) message(FATAL_ERROR "No source files found of ${CC_ARGS_NAME}.") endif() if(CC_ARGS_VERSION) string(REPLACE "-" "_" MACRO_PREFIX "${CC_ARGS_NAME}") list(APPEND CC_ARGS_DEFS ${MACRO_PREFIX}_VERSION="${CC_ARGS_VERSION}") endif() if(CC_ARGS_EXCLUDE) set(EXCLUDE_OPTION EXCLUDE_FROM_ALL) endif() set(PROTO_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) if(CC_ARGS_PROTOROOT) get_filename_component(PROTO_ROOT ${CC_ARGS_PROTOROOT} ABSOLUTE) endif() # Compile proto files to C++ sources set(CPP_OUTPATH "${CMAKE_CURRENT_BINARY_DIR}") foreach(PROTO_FILE ${CC_ARGS_SRCS}) get_filename_component(PROTO_FILE ${PROTO_FILE} ABSOLUTE) if(NOT ${PROTO_FILE} MATCHES "\\.proto$$") message(FATAL_ERROR "Unrecognized proto file ${PROTOFILE}") endif() if(NOT ${PROTO_FILE} MATCHES "^${PROTO_ROOT}") message(FATAL_ERROR "'${PROTO_FILE}' NOT IN '${PROTO_ROOT}'") endif() string( REGEX REPLACE "^${PROTO_ROOT}(/?)" "" ROOT_CLEANED_FILE ${PROTO_FILE} ) string(REGEX REPLACE "\\.proto$$" "" EXT_CLEANED_FILE ${ROOT_CLEANED_FILE}) set(CPP_FILE "${CPP_OUTPATH}/${EXT_CLEANED_FILE}.pb.cc") set(HDR_FILE "${CPP_OUTPATH}/${EXT_CLEANED_FILE}.pb.h") set(INJ_FILE "${CPP_OUTPATH}/${EXT_CLEANED_FILE}.pb.cmake") file(RELATIVE_PATH REL_CPP_FILE ${CMAKE_BINARY_DIR} ${CPP_FILE}) set(INJECTED_SCRIPT "foreach(SRC ${EXT_CLEANED_FILE}.pb.cc ${EXT_CLEANED_FILE}.pb.h)\n" " file(READ \$\{SRC\} SRC_CODE)\n" " file(REMOVE \$\{SRC\})\n" " file(APPEND \$\{SRC\} \"#ifdef __GNUC__\\n\")\n" " file(APPEND \$\{SRC\} \"#pragma GCC diagnostic push\\n\")\n" " file(APPEND \$\{SRC\} \"#pragma GCC diagnostic ignored \\\"-Wshadow\\\"\\n\")\n" " file(APPEND \$\{SRC\} \"#pragma GCC diagnostic ignored \\\"-Wunused-parameter\\\"\\n\")\n" " file(APPEND \$\{SRC\} \"#endif\\n\\n\")\n" " file(APPEND \$\{SRC\} \"\$\{SRC_CODE\}\")\n" " file(APPEND \$\{SRC\} \"\\n#ifdef __GNUC__\\n\")\n" " file(APPEND \$\{SRC\} \"#pragma GCC diagnostic pop\\n\")\n" " file(APPEND \$\{SRC\} \"#endif\\n\")\n" "endforeach()\n" ) file(WRITE "${INJ_FILE}" ${INJECTED_SCRIPT}) add_custom_command( OUTPUT "${CPP_FILE}" "${HDR_FILE}" # COMMAND ${CMAKE_COMMAND} -E make_directory ${CPP_OUTPATH} COMMAND ${CC_PROTOBUF_PROTOC} --cpp_out "${CPP_OUTPATH}" --python_out "${CPP_OUTPATH}" --proto_path "${PROTO_ROOT}" "${PROTO_FILE}" COMMAND ${CMAKE_COMMAND} -P "${INJ_FILE}" DEPENDS "${PROTO_FILE}" COMMENT "Generating CXX source ${REL_CPP_FILE}" VERBATIM ) list(APPEND CC_SRCS "${CPP_FILE}" "${HDR_FILE}") endforeach() # Compile C++ sources if(CC_ARGS_SHARED AND CC_ARGS_STATIC) _add_library(${CC_ARGS_NAME} "${EXCLUDE_OPTION}" "${CC_SRCS}") elseif(CC_ARGS_SHARED) add_library(${CC_ARGS_NAME} SHARED ${EXCLUDE_OPTION} ${CC_SRCS}) elseif(CC_ARGS_STATIC) add_library(${CC_ARGS_NAME} STATIC ${EXCLUDE_OPTION} ${CC_SRCS}) else() add_library(${CC_ARGS_NAME} ${EXCLUDE_OPTION} ${CC_SRCS}) endif() if(TARGET ${CC_ARGS_NAME}_objects) _cc_target_properties( NAME "${CC_ARGS_NAME}_objects" INCS "${CPP_OUTPATH};${CC_PROTOBUF_INCS}" LIBS "${CC_PROTOBUF_LIBS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) endif() if(TARGET ${CC_ARGS_NAME}_static) _cc_target_properties( NAME "${CC_ARGS_NAME}_static" PUBINCS "${CPP_OUTPATH};${CC_PROTOBUF_INCS}" LIBS "${CC_PROTOBUF_LIBS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) if(CC_ARGS_PACKED) install( TARGETS ${CC_ARGS_NAME}_static ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) endif() endif() _cc_target_properties( NAME "${CC_ARGS_NAME}" PUBINCS "${CPP_OUTPATH};${CC_PROTOBUF_INCS}" LIBS "${CC_PROTOBUF_LIBS}" CXXFLAGS "${CC_ARGS_CXXFLAGS}" LDFLAGS "${CC_ARGS_LDFLAGS}" DEPS "${CC_ARGS_DEPS}" VERSION "${CC_ARGS_VERSION}" "${CC_ARGS_UNPARSED_ARGUMENTS}" ) if(CC_ARGS_PACKED) install( TARGETS ${CC_ARGS_NAME} ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) endif() endfunction() ## Add a subdirectory to the build function(cuda_directory) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cc_directory(${ARGN}) endfunction() ## Add subdirectories to the build function(cuda_directories) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cc_directories(${ARGN}) endfunction() ## Set the properties of cuda target function(_cuda_target_properties) cmake_parse_arguments( CUDA_ARGS "STRICT;ALWAYS_LINK" "NAME;VERSION;C_STANDARD;CXX_STANDARD" "INCS;PUBINCS;DEFS;LIBS;CFLAGS;CXXFLAGS;CUDAFLAGS;LDFLAGS;DEPS" ${ARGN} ) if(NOT CUDA_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() get_target_property(TARGET_TYPE ${CUDA_ARGS_NAME} TYPE) if(("${TARGET_TYPE}" STREQUAL "SHARED_LIBRARY") OR ("${TARGET_TYPE}" STREQUAL "STATIC_LIBRARY") OR ("${TARGET_TYPE}" STREQUAL "EXECUTABLE")) set(TARGET_LINKABLE TRUE) endif() if(CUDA_ARGS_ALWAYS_LINK) if(("${TARGET_TYPE}" STREQUAL "STATIC_LIBRARY") OR ("${TARGET_TYPE}" STREQUAL "OBJECT_LIBRARY")) set_property(TARGET ${CUDA_ARGS_NAME} PROPERTY ALWAYS_LINK TRUE) endif() endif() # Set the warning level of compiling if(CUDA_ARGS_STRICT) target_compile_options( ${CUDA_ARGS_NAME} PRIVATE "${BAZEL_CUDA_STRICT_COMPILE_FLAGS}" ) if(TARGET_LINKABLE) target_link_libraries( ${CUDA_ARGS_NAME} "${BAZEL_CUDA_STRICT_LINK_FLAGS}" ) endif() else() target_compile_options( ${CUDA_ARGS_NAME} PRIVATE "${BAZEL_CUDA_UNSTRICT_COMPILE_FLAGS}" ) if(TARGET_LINKABLE) target_link_libraries( ${CUDA_ARGS_NAME} "${BAZEL_CUDA_UNSTRICT_LINK_FLAGS}" ) endif() endif() target_compile_options( ${CUDA_ARGS_NAME} PRIVATE "$<$:-ccbin=${CMAKE_CXX_COMPILER}>" ) if(CUDA_ARGS_DEFS) target_compile_definitions(${CUDA_ARGS_NAME} PRIVATE "${CUDA_ARGS_DEFS}") endif() if(CUDA_ARGS_CFLAGS OR CUDA_ARGS_CXXFLAGS OR CUDA_ARGS_CUDAFLAGS) target_compile_options( ${CUDA_ARGS_NAME} PRIVATE "$<$:${CUDA_ARGS_CFLAGS}>" "$<$:${CUDA_ARGS_CXXFLAGS}>" "$<$:${CUDA_ARGS_CUDAFLAGS}>" ) endif() if(CUDA_ARGS_LDFLAGS) string(REPLACE ";" " " CUDA_ARGS_LDFLAGS "${CUDA_ARGS_LDFLAGS}") set_property( TARGET ${CUDA_ARGS_NAME} PROPERTY LINK_FLAGS "${CUDA_ARGS_LDFLAGS}" ) endif() if(CUDA_ARGS_INCS) _absolute_paths(INC_DIRS ${CUDA_ARGS_INCS}) target_include_directories(${CUDA_ARGS_NAME} PRIVATE "${INC_DIRS}") endif() target_include_directories( ${CUDA_ARGS_NAME} PRIVATE "${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}" ) if(BAZEL_WORKSPACE_DIR) target_include_directories( ${CUDA_ARGS_NAME} PRIVATE "${BAZEL_WORKSPACE_DIR}" ) endif() if(CUDA_ARGS_PUBINCS) _absolute_paths(INC_DIRS ${CUDA_ARGS_PUBINCS}) target_include_directories(${CUDA_ARGS_NAME} PUBLIC "${INC_DIRS}") endif() if(CUDA_ARGS_LIBS) if(NOT TARGET_LINKABLE) _targets_link_dependencies(${CUDA_ARGS_NAME} ${CUDA_ARGS_LIBS}) else() if ("${TARGET_TYPE}" STREQUAL "EXECUTABLE") _target_link_libraries(${CUDA_ARGS_NAME} "${CUDA_ARGS_LIBS}") else() target_link_libraries(${CUDA_ARGS_NAME} "${CUDA_ARGS_LIBS}") endif() endif() endif() if(CUDA_ARGS_DEPS) add_dependencies(${CUDA_ARGS_NAME} "${CUDA_ARGS_DEPS}") endif() if(CUDA_ARGS_VERSION) set_property( TARGET ${CUDA_ARGS_NAME} PROPERTY VERSION "${CUDA_ARGS_VERSION}" ) endif() if(NOT CUDA_C_STANDARD) set(CUDA_C_STANDARD 99) endif() if(NOT CUDA_CXX_STANDARD) set(CUDA_CXX_STANDARD 11) endif() set_target_properties( ${CUDA_ARGS_NAME} PROPERTIES DEFINE_SYMBOL "" C_STANDARD ${CUDA_C_STANDARD} CXX_STANDARD ${CUDA_CXX_STANDARD} C_STANDARD_REQUIRED ON C_EXTENSIONS ON CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF CUDA_STANDARD 11 CUDA_STANDARD_REQUIRED ON CUDA_EXTENSIONS OFF WINDOWS_EXPORT_ALL_SYMBOLS ON ) endfunction() ## Build a CUDA static or shared library function(cuda_library) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cmake_parse_arguments( CUDA_ARGS "STATIC;SHARED;EXCLUDE;PACKED" "NAME;VERSION" "SRCS;INCS;PUBINCS;DEFS;LIBS;CFLAGS;CXXFLAGS;CUDAFLAGS;LDFLAGS;DEPS;PACKED_EXCS" ${ARGN} ) if(NOT CUDA_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CUDA_ARGS_SRCS ${CUDA_ARGS_SRCS}) if(NOT CUDA_ARGS_SRCS) message(FATAL_ERROR "No source files found of ${CUDA_ARGS_NAME}.") endif() if(CUDA_ARGS_VERSION) string(REPLACE "-" "_" MACRO_PREFIX "${CUDA_ARGS_NAME}") list(APPEND CUDA_ARGS_DEFS ${MACRO_PREFIX}_VERSION="${CUDA_ARGS_VERSION}") endif() if(CUDA_ARGS_EXCLUDE) set(EXCLUDE_OPTION EXCLUDE_FROM_ALL) endif() if(CUDA_ARGS_SHARED AND CUDA_ARGS_STATIC) _add_library(${CUDA_ARGS_NAME} "${EXCLUDE_OPTION}" "${CUDA_ARGS_SRCS}") elseif(CUDA_ARGS_SHARED) add_library(${CUDA_ARGS_NAME} SHARED ${EXCLUDE_OPTION} ${CUDA_ARGS_SRCS}) elseif(CUDA_ARGS_STATIC) add_library(${CUDA_ARGS_NAME} STATIC ${EXCLUDE_OPTION} ${CUDA_ARGS_SRCS}) else() add_library(${CUDA_ARGS_NAME} ${EXCLUDE_OPTION} ${CUDA_ARGS_SRCS}) endif() if(TARGET ${CUDA_ARGS_NAME}_objects) _cuda_target_properties( NAME "${CUDA_ARGS_NAME}_objects" INCS "${CUDA_ARGS_INCS};${CUDA_ARGS_PUBINCS}" DEFS "${CUDA_ARGS_DEFS}" LIBS "${CUDA_ARGS_LIBS}" CFLAGS "${CUDA_ARGS_CFLAGS}" CXXFLAGS "${CUDA_ARGS_CXXFLAGS}" CUDAFLAGS "${CUDA_ARGS_CUDAFLAGS}" LDFLAGS "${CUDA_ARGS_LDFLAGS}" DEPS "${CUDA_ARGS_DEPS}" "${CUDA_ARGS_UNPARSED_ARGUMENTS}" ) endif() if(TARGET ${CUDA_ARGS_NAME}_static) _cuda_target_properties( NAME "${CUDA_ARGS_NAME}_static" INCS "${CUDA_ARGS_INCS}" PUBINCS "${CUDA_ARGS_PUBINCS}" DEFS "${CUDA_ARGS_DEFS}" LIBS "${CUDA_ARGS_LIBS}" CFLAGS "${CUDA_ARGS_CFLAGS}" CXXFLAGS "${CUDA_ARGS_CXXFLAGS}" CUDAFLAGS "${CUDA_ARGS_CUDAFLAGS}" LDFLAGS "${CUDA_ARGS_LDFLAGS}" DEPS "${CUDA_ARGS_DEPS}" "${CUDA_ARGS_UNPARSED_ARGUMENTS}" ) if(CUDA_ARGS_PACKED) install( TARGETS ${CUDA_ARGS_NAME}_static ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) endif() endif() _cuda_target_properties( NAME "${CUDA_ARGS_NAME}" INCS "${CUDA_ARGS_INCS}" PUBINCS "${CUDA_ARGS_PUBINCS}" DEFS "${CUDA_ARGS_DEFS}" LIBS "${CUDA_ARGS_LIBS}" CFLAGS "${CUDA_ARGS_CFLAGS}" CXXFLAGS "${CUDA_ARGS_CXXFLAGS}" CUDAFLAGS "${CUDA_ARGS_CUDAFLAGS}" LDFLAGS "${CUDA_ARGS_LDFLAGS}" DEPS "${CUDA_ARGS_DEPS}" VERSION "${CUDA_ARGS_VERSION}" "${CUDA_ARGS_UNPARSED_ARGUMENTS}" ) if(CUDA_ARGS_PACKED) install( TARGETS ${CUDA_ARGS_NAME} ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) if(CUDA_ARGS_PUBINCS) foreach(PACKED_EXCLUDE ${CUDA_ARGS_PACKED_IGORNES}) list(APPEND PATTERN_EXCLUDES "PATTERN;${PACKED_EXCLUDE};EXCLUDE") endforeach() install( DIRECTORY ${CUDA_ARGS_PUBINCS} DESTINATION ${CMAKE_INSTALL_INCDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.hxx" PATTERN "*.cuh" ${PATTERN_EXCLUDES} ) endif() endif() endfunction() ## Build a CUDA executable program function(cuda_binary) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cmake_parse_arguments( CUDA_ARGS "PACKED" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;CUDAFLAGS;LDFLAGS;DEPS" ${ARGN} ) if(NOT CUDA_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CUDA_ARGS_SRCS ${CUDA_ARGS_SRCS}) if(NOT CUDA_ARGS_SRCS) message(FATAL_ERROR "No source files found of ${CUDA_ARGS_NAME}.") endif() if(CUDA_ARGS_VERSION) string(REPLACE "-" "_" MACRO_PREFIX "${CUDA_ARGS_NAME}") list(APPEND CUDA_ARGS_DEFS ${MACRO_PREFIX}_VERSION="${CUDA_ARGS_VERSION}") endif() add_executable(${CUDA_ARGS_NAME} ${CUDA_ARGS_SRCS}) if(CUDA_ARGS_PACKED) install( TARGETS ${CUDA_ARGS_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) endif() _cuda_target_properties( NAME "${CUDA_ARGS_NAME}" INCS "${CUDA_ARGS_INCS}" DEFS "${CUDA_ARGS_DEFS}" LIBS "${CUDA_ARGS_LIBS}" CFLAGS "${CUDA_ARGS_CFLAGS}" CXXFLAGS "${CUDA_ARGS_CXXFLAGS}" CUDAFLAGS "${CUDA_ARGS_CUDAFLAGS}" LDFLAGS "${CUDA_ARGS_LDFLAGS}" DEPS "${CUDA_ARGS_DEPS}" VERSION "${CUDA_ARGS_VERSION}" "${CUDA_ARGS_UNPARSED_ARGUMENTS}" ) endfunction() ## Build a CUDA executable test program function(cuda_test) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cmake_parse_arguments( CUDA_ARGS "" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;CUDAFLAGS;LDFLAGS;DEPS;ARGS" ${ARGN} ) if(NOT CUDA_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CUDA_ARGS_SRCS ${CUDA_ARGS_SRCS}) if(NOT CUDA_ARGS_SRCS) message(FATAL_ERROR "No source files found of ${CUDA_ARGS_NAME}.") endif() if(CUDA_ARGS_VERSION) string(REPLACE "-" "_" MACRO_PREFIX "${CUDA_ARGS_NAME}") list(APPEND CUDA_ARGS_DEFS ${MACRO_PREFIX}_VERSION="${CUDA_ARGS_VERSION}") endif() add_executable(${CUDA_ARGS_NAME} EXCLUDE_FROM_ALL ${CUDA_ARGS_SRCS}) _cuda_target_properties( NAME "${CUDA_ARGS_NAME}" INCS "${CUDA_ARGS_INCS}" DEFS "${CUDA_ARGS_DEFS}" LIBS "${CUDA_ARGS_LIBS}" CFLAGS "${CUDA_ARGS_CFLAGS}" CXXFLAGS "${CUDA_ARGS_CXXFLAGS}" CUDAFLAGS "${CUDA_ARGS_CUDAFLAGS}" LDFLAGS "${CUDA_ARGS_LDFLAGS}" DEPS "${CUDA_ARGS_DEPS}" "${CUDA_ARGS_UNPARSED_ARGUMENTS}" ) add_dependencies(unittest ${CUDA_ARGS_NAME}) add_custom_target( unittest.${CUDA_ARGS_NAME} COMMAND $ "${CUDA_ARGS_ARGS}" WORKING_DIRECTORY ${PROJECT_BINARY_DIR} DEPENDS ${CUDA_ARGS_NAME} ) add_test( NAME ${CUDA_ARGS_NAME} COMMAND $ "${CUDA_ARGS_ARGS}" WORKING_DIRECTORY ${PROJECT_BINARY_DIR} ) endfunction() ## Add existing test cases to a test suite function(cuda_test_suite) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cc_test_suite(${ARGN}) endfunction() ## Import a C/C++/CUDA static or shared library function(cuda_import) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cmake_parse_arguments( CUDA_ARGS "STATIC;SHARED;PACKED" "NAME;PATH;IMPLIB" "INCS;PUBINCS;DEPS;PACKED_EXCLUDES" ${ARGN} ) if(NOT CUDA_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB CUDA_ARGS_PATH ${CUDA_ARGS_PATH}) if(NOT CUDA_ARGS_PATH) message(FATAL_ERROR "No imported target file found of ${CUDA_ARGS_NAME}.") endif() if(MSVC AND CUDA_ARGS_SHARED AND NOT CUDA_ARGS_IMPLIB) string(REGEX REPLACE ".[Dd][Ll][Ll]$" ".lib" CUDA_ARGS_IMPLIB ${CUDA_ARGS_PATH} ) endif() if(CUDA_ARGS_SHARED) add_library(${CUDA_ARGS_NAME} SHARED IMPORTED GLOBAL) elseif(CUDA_ARGS_STATIC) add_library(${CUDA_ARGS_NAME} STATIC IMPORTED GLOBAL) else() add_library(${CUDA_ARGS_NAME} UNKNOWN IMPORTED GLOBAL) endif() set_property( TARGET ${CUDA_ARGS_NAME} PROPERTY IMPORTED_LOCATION ${CUDA_ARGS_PATH} ) if(MSVC AND CUDA_ARGS_SHARED) set_property( TARGET ${CUDA_ARGS_NAME} PROPERTY IMPORTED_IMPLIB ${CUDA_ARGS_IMPLIB} ) endif() if(CUDA_ARGS_INCS) _absolute_paths(INC_DIRS ${CUDA_ARGS_INCS}) foreach(INC_DIR ${INC_DIRS}) set_property( TARGET ${CUDA_ARGS_NAME} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${INC_DIR}" ) endforeach() endif() if(CUDA_ARGS_PUBINCS) _absolute_paths(INC_DIRS ${CUDA_ARGS_PUBINCS}) foreach(INC_DIR ${INC_DIRS}) set_property( TARGET ${CUDA_ARGS_NAME} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${INC_DIR}" ) endforeach() endif() if(CUDA_ARGS_DEPS) add_dependencies(${CUDA_ARGS_NAME} "${CUDA_ARGS_DEPS}") endif() if(CUDA_ARGS_PACKED) install( TARGETS ${CUDA_ARGS_NAME} ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) if(CUDA_ARGS_PUBINCS) foreach(PACKED_EXCLUDE ${CUDA_ARGS_PACKED_EXCLUDES}) list(APPEND PATTERN_EXCLUDES "PATTERN;${PACKED_EXCLUDE};EXCLUDE") endforeach() install( DIRECTORY ${CUDA_ARGS_PUBINCS} DESTINATION ${CMAKE_INSTALL_INCDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.hxx" PATTERN "*.cuh" ${PATTERN_EXCLUDES} ) endif() endif() endfunction() ## Import a C/C++/CUDA interface library function(cuda_interface) if(NOT CMAKE_CUDA_COMPILER) message(FATAL_ERROR "No CUDA language supported.") endif() cmake_parse_arguments( CUDA_ARGS "PACKED" "NAME" "INCS;PUBINCS;DEPS;PACKED_EXCLUDES" ${ARGN} ) if(NOT CUDA_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() add_library(${CUDA_ARGS_NAME} INTERFACE GLOBAL) if(CUDA_ARGS_INCS) _absolute_paths(INC_DIRS ${CUDA_ARGS_INCS}) target_include_directories(${CUDA_ARGS_NAME} INTERFACE "${INC_DIRS}") endif() if(CUDA_ARGS_PUBINCS) _absolute_paths(INC_DIRS ${CUDA_ARGS_PUBINCS}) target_include_directories(${CUDA_ARGS_NAME} INTERFACE "${INC_DIRS}") endif() if(CUDA_ARGS_DEPS) add_dependencies(${CUDA_ARGS_NAME} "${CUDA_ARGS_DEPS}") endif() if(CUDA_ARGS_PACKED AND CUDA_ARGS_PUBINCS) foreach(PACKED_EXCLUDE ${CUDA_ARGS_PACKED_EXCLUDES}) list(APPEND PATTERN_EXCLUDES "PATTERN;${PACKED_EXCLUDE};EXCLUDE") endforeach() install( DIRECTORY ${CUDA_ARGS_PUBINCS} DESTINATION ${CMAKE_INSTALL_INCDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.hxx" PATTERN "*.cuh" ${PATTERN_EXCLUDES} ) endif() endfunction() ## Build a C/C++/CUDA executable google test program function(cuda_gtest) cmake_parse_arguments( CUDA_ARGS "" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;CUDAFLAGS;LDFLAGS;DEPS;ARGS" ${ARGN} ) _find_gtest() cuda_test( NAME "${CUDA_ARGS_NAME}" VERSION "${CUDA_ARGS_VERSION}" SRCS "${CUDA_ARGS_SRCS}" INCS "${CUDA_ARGS_INCS};${FIND_GTEST_INCS}" DEFS "${CUDA_ARGS_DEFS}" LIBS "${CUDA_ARGS_LIBS};${FIND_GTEST_LIBS}" CFLAGS "${CUDA_ARGS_CFLAGS}" CXXFLAGS "${CUDA_ARGS_CXXFLAGS}" CUDAFLAGS "${CUDA_ARGS_CUDAFLAGS}" LDFLAGS "${CUDA_ARGS_LDFLAGS}" DEPS "${CUDA_ARGS_DEPS}" ARGS "${CUDA_ARGS_ARGS}" ) endfunction() ## Build a C/C++/CUDA executable google mock program function(cuda_gmock) cmake_parse_arguments( CUDA_ARGS "" "NAME;VERSION" "SRCS;INCS;DEFS;LIBS;CFLAGS;CXXFLAGS;CUDAFLAGS;LDFLAGS;DEPS;ARGS" ${ARGN} ) _find_gmock() cuda_test( NAME "${CUDA_ARGS_NAME}" VERSION "${CUDA_ARGS_VERSION}" SRCS "${CUDA_ARGS_SRCS}" INCS "${CUDA_ARGS_INCS};${FIND_GMOCK_INCS}" DEFS "${CUDA_ARGS_DEFS}" LIBS "${CUDA_ARGS_LIBS};${FIND_GMOCK_LIBS}" CFLAGS "${CUDA_ARGS_CFLAGS}" CXXFLAGS "${CUDA_ARGS_CXXFLAGS}" CUDAFLAGS "${CUDA_ARGS_CUDAFLAGS}" LDFLAGS "${CUDA_ARGS_LDFLAGS}" DEPS "${CUDA_ARGS_DEPS}" ARGS "${CUDA_ARGS_ARGS}" ) endfunction() ## Add a subdirectory to the build function(go_directory) add_subdirectory(${ARGN}) endfunction() ## Add subdirectories to the build function(go_directories) foreach(SRC_DIR ${ARGN}) add_subdirectory(${SRC_DIR}) endforeach() endfunction() ## Build a go executable program function(go_binary) find_program( GO_EXECUTABLE go PATHS $ENV{HOME}/go ENV GOROOT GOPATH PATH_SUFFIXES bin ) if(NOT GO_EXECUTABLE) message(FATAL_ERROR "No go language compiler found.") endif() cmake_parse_arguments( GO_ARGS "PACKED" "NAME" "GOPATH;SRCS;ASMFLAGS;GCFLAGS;LDFLAGS;DEPS" ${ARGN} ) if(NOT GO_ARGS_NAME) message(FATAL_ERROR "No target name privated.") endif() file(GLOB GO_ARGS_SRCS ${GO_ARGS_SRCS}) if(NOT GO_ARGS_SRCS) message(FATAL_ERROR "No source files/directories found of ${GO_ARGS_NAME}.") endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") string(REPLACE ";" "\;" GO_ARGS_GOPATH "${GO_ARGS_GOPATH}") else() string(REPLACE ";" ":" GO_ARGS_GOPATH "${GO_ARGS_GOPATH}") endif() set( GO_OUTPUT_FILE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${GO_ARGS_NAME}${CMAKE_EXECUTABLE_SUFFIX} ) file(RELATIVE_PATH GO_OUTPUT_REL_FILE ${CMAKE_BINARY_DIR} ${GO_OUTPUT_FILE}) add_custom_target( ${GO_ARGS_NAME} COMMAND ${CMAKE_COMMAND} -E env GOPATH="${GO_ARGS_GOPATH}" "${GO_EXECUTABLE}" build -v -buildmode=exe -compiler=gc -gcflags="${GO_ARGS_GCFLAGS}" -asmflags="${GO_ARGS_ASMFLAGS}" -ldflags="${GO_ARGS_LDFLAGS}" -o "${GO_OUTPUT_FILE}" "${GO_ARGS_SRCS}" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DEPENDS "${GO_ARGS_DEPS}" COMMENT "Building GO executable ${GO_OUTPUT_REL_FILE}" ) if(GO_ARGS_PACKED) install(PROGRAMS ${GO_OUTPUT_FILE} DESTINATION "${CMAKE_INSTALL_BINDIR}") endif() endfunction() ## Fetch content function(_fetch_content) cmake_parse_arguments( DL_ARGS "" "NAME;PATH;GIT_URL;GIT_TAG;HG_URL;HG_TAG;SVN_URL;SVN_REV;URL;URL_HASH" "" ${ARGN} ) if(NOT DL_ARGS_NAME) message(FATAL_ERROR "No fetch name privated.") endif() if(NOT DL_ARGS_PATH) # Download to current source directory set(DL_ARGS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${DL_ARGS_NAME}") endif() set( CMAKELISTS_CONTENT "cmake_minimum_required(VERSION 3.1)\n" "project(${DL_ARGS_NAME})\n" "include(ExternalProject)\n" "ExternalProject_Add(\n" " ${DL_ARGS_NAME}\n" " PREFIX \"external\"\n" " GIT_REPOSITORY \"${DL_ARGS_GIT_URL}\"\n" " GIT_TAG \"${DL_ARGS_GIT_TAG}\"\n" " HG_REPOSITORY \"${DL_ARGS_HG_URL}\"\n" " HG_TAG \"${DL_ARGS_HG_TAG}\"\n" " SVN_REPOSITORY \"${DL_ARGS_SVN_URL}\"\n" " SVN_REVISION \"${DL_ARGS_SVN_REV}\"\n" " URL \"${DL_ARGS_URL}\"\n" " URL_HASH \"${DL_ARGS_URL_HASH}\"\n" " SOURCE_DIR \"${DL_ARGS_PATH}\"\n" " BINARY_DIR \"\"\n" " CONFIGURE_COMMAND \"\"\n" " BUILD_COMMAND \"\"\n" " INSTALL_COMMAND \"\"\n" " TEST_COMMAND \"\"\n" " LOG_DOWNLOAD ON\n" " )\n" ) set( CMAKELISTS_DIRECTORY "${PROJECT_BINARY_DIR}/downloads/${DL_ARGS_NAME}" ) add_custom_target( external.${DL_ARGS_NAME} COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" . && "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${CMAKELISTS_DIRECTORY}" ) # Write a cmake script into folder file(WRITE "${CMAKELISTS_DIRECTORY}/CMakeLists.txt" ${CMAKELISTS_CONTENT}) execute_process( COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY "${CMAKELISTS_DIRECTORY}" ) execute_process( COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${CMAKELISTS_DIRECTORY}" ) endfunction() ## Download a git repository function(git_repository) cmake_parse_arguments(GIT_ARGS "" "NAME;PATH;URL;TAG" "" ${ARGN}) if(NOT GIT_ARGS_NAME) message(FATAL_ERROR "No repository name privated.") endif() if(NOT GIT_ARGS_URL) message(FATAL_ERROR "No repository URL privated.") endif() if(GIT_ARGS_PATH AND NOT IS_ABSOLUTE ${GIT_ARGS_PATH}) get_filename_component(GIT_ARGS_PATH ${GIT_ARGS_PATH} ABSOLUTE) endif() _fetch_content( NAME "${GIT_ARGS_NAME}" PATH "${GIT_ARGS_PATH}" GIT_URL "${GIT_ARGS_URL}" GIT_TAG "${GIT_ARGS_TAG}" ) endfunction() ## Download a hg repository function(hg_repository) cmake_parse_arguments(HG_ARGS "" "NAME;PATH;URL;TAG" "" ${ARGN}) if(NOT HG_ARGS_NAME) message(FATAL_ERROR "No repository name privated.") endif() if(NOT HG_ARGS_URL) message(FATAL_ERROR "No repository URL privated.") endif() if(HG_ARGS_PATH AND NOT IS_ABSOLUTE ${HG_ARGS_PATH}) get_filename_component(HG_ARGS_PATH ${HG_ARGS_PATH} ABSOLUTE) endif() _fetch_content( NAME "${HG_ARGS_NAME}" PATH "${HG_ARGS_PATH}" HG_URL "${HG_ARGS_URL}" HG_TAG "${HG_ARGS_TAG}" ) endfunction() ## Download a svn repository function(svn_repository) cmake_parse_arguments(SVN_ARGS "" "NAME;PATH;URL;REV" "" ${ARGN}) if(NOT SVN_ARGS_NAME) message(FATAL_ERROR "No repository name privated.") endif() if(NOT SVN_ARGS_URL) message(FATAL_ERROR "No repository URL privated.") endif() if(SVN_ARGS_PATH AND NOT IS_ABSOLUTE ${SVN_ARGS_PATH}) get_filename_component(SVN_ARGS_PATH ${SVN_ARGS_PATH} ABSOLUTE) endif() _fetch_content( NAME "${SVN_ARGS_NAME}" PATH "${SVN_ARGS_PATH}" SVN_URL "${SVN_ARGS_URL}" SVN_REV "${SVN_ARGS_REV}" ) endfunction() ## Download a http archive function(http_archive) cmake_parse_arguments(HTTP_ARGS "" "NAME;PATH;URL;SHA256;SHA1;MD5" "" ${ARGN}) if(NOT HTTP_ARGS_NAME) message(FATAL_ERROR "No archive name privated.") endif() if(NOT HTTP_ARGS_URL) message(FATAL_ERROR "No archive URL privated.") endif() if(HTTP_ARGS_PATH AND NOT IS_ABSOLUTE ${HTTP_ARGS_PATH}) get_filename_component(HTTP_ARGS_PATH ${HTTP_ARGS_PATH} ABSOLUTE) endif() if(HTTP_ARGS_SHA256) set(HTTP_URL_HASH "SHA256=${HTTP_ARGS_SHA256}") elseif(HTTP_ARGS_SHA1) set(HTTP_URL_HASH "SHA1=${HTTP_ARGS_SHA1}") elseif(HTTP_ARGS_MD5) set(HTTP_URL_HASH "MD5=${HTTP_ARGS_MD5}") else() set(HTTP_URL_HASH "") endif() _fetch_content( NAME "${HTTP_ARGS_NAME}" PATH "${HTTP_ARGS_PATH}" URL "${HTTP_ARGS_URL}" URL_HASH "${HTTP_URL_HASH}" ) endfunction() ## Retrieve a version string from GIT function(git_version _RESULT _SOURCES_DIR) find_package(Git REQUIRED) if(NOT IS_ABSOLUTE ${_SOURCES_DIR}) get_filename_component(_SOURCES_DIR ${_SOURCES_DIR} ABSOLUTE) endif() # git describe --tags execute_process( COMMAND "${GIT_EXECUTABLE}" describe --tags WORKING_DIRECTORY "${_SOURCES_DIR}" RESULT_VARIABLE GIT_VER_RESULT OUTPUT_VARIABLE GIT_VER_OUTPUT ERROR_VARIABLE GIT_VER_ERROR ) if(GIT_VER_RESULT EQUAL 0) string(STRIP ${GIT_VER_OUTPUT} GIT_VER_OUTPUT) set(${_RESULT} "${GIT_VER_OUTPUT}" PARENT_SCOPE) return() endif() # git rev-parse --short HEAD execute_process( COMMAND "${GIT_EXECUTABLE}" rev-parse --short HEAD WORKING_DIRECTORY "${_SOURCES_DIR}" RESULT_VARIABLE GIT_VER_RESULT OUTPUT_VARIABLE GIT_VER_OUTPUT ERROR_VARIABLE GIT_VER_ERROR ) if(GIT_VER_RESULT EQUAL 0) string(STRIP ${GIT_VER_OUTPUT} GIT_VER_OUTPUT) set(${_RESULT} "g${GIT_VER_OUTPUT}" PARENT_SCOPE) return() endif() set(${_RESULT} "" PARENT_SCOPE) endfunction() ## Retrieve a version string from HG function(hg_version _RESULT _SOURCES_DIR) find_package(Hg REQUIRED) if(NOT IS_ABSOLUTE ${_SOURCES_DIR}) get_filename_component(_SOURCES_DIR ${_SOURCES_DIR} ABSOLUTE) endif() # hg log -T "{latesttagdistance}" -r . execute_process( COMMAND "${HG_EXECUTABLE}" log -T "{latesttagdistance}" -r . WORKING_DIRECTORY "${_SOURCES_DIR}" RESULT_VARIABLE HG_VER_RESULT OUTPUT_VARIABLE HG_VER_OUTPUT ERROR_VARIABLE HG_VER_ERROR ) if(HG_VER_RESULT EQUAL 0) string(STRIP ${HG_VER_OUTPUT} HG_VER_OUTPUT) if(HG_VER_OUTPUT STREQUAL "0") # hg log -T "{latesttag}" -r . execute_process( COMMAND "${HG_EXECUTABLE}" log -T "{latesttag}" -r . WORKING_DIRECTORY "${_SOURCES_DIR}" RESULT_VARIABLE HG_VER_RESULT OUTPUT_VARIABLE HG_VER_OUTPUT ERROR_VARIABLE HG_VER_ERROR ) else() # hg log -T "{latesttag}-{latesttagdistance}-h{node|short}" -r . execute_process( COMMAND "${HG_EXECUTABLE}" log -T "{latesttag}-{latesttagdistance}-h{node|short}" -r . WORKING_DIRECTORY "${_SOURCES_DIR}" RESULT_VARIABLE HG_VER_RESULT OUTPUT_VARIABLE HG_VER_OUTPUT ERROR_VARIABLE HG_VER_ERROR ) endif() if(HG_VER_RESULT EQUAL 0) string(STRIP ${HG_VER_OUTPUT} HG_VER_OUTPUT) if(NOT HG_VER_OUTPUT MATCHES "^null.*") set(${_RESULT} "${HG_VER_OUTPUT}" PARENT_SCOPE) return() endif() endif() endif() # hg log -T "h{node|short}" -r . execute_process( COMMAND "${HG_EXECUTABLE}" log -T "h{node|short}" -r . WORKING_DIRECTORY "${_SOURCES_DIR}" RESULT_VARIABLE HG_VER_RESULT OUTPUT_VARIABLE HG_VER_OUTPUT ERROR_VARIABLE HG_VER_ERROR ) if(HG_VER_RESULT EQUAL 0) string(STRIP ${HG_VER_OUTPUT} HG_VER_OUTPUT) set(${_RESULT} "${HG_VER_OUTPUT}" PARENT_SCOPE) return() endif() set(${_RESULT} "" PARENT_SCOPE) endfunction() ## Retrieve a version string from SVN function(svn_version _RESULT _SOURCES_DIR) find_package(Subversion REQUIRED) if(NOT IS_ABSOLUTE ${_SOURCES_DIR}) get_filename_component(_SOURCES_DIR ${_SOURCES_DIR} ABSOLUTE) endif() # svn info --show-item revision execute_process( COMMAND "${Subversion_SVN_EXECUTABLE}" info --show-item revision WORKING_DIRECTORY "${_SOURCES_DIR}" RESULT_VARIABLE SVN_VER_RESULT OUTPUT_VARIABLE SVN_VER_OUTPUT ERROR_VARIABLE SVN_VER_ERROR ) if(SVN_VER_RESULT EQUAL 0) string(STRIP ${SVN_VER_OUTPUT} SVN_VER_OUTPUT) set(${_RESULT} "r${SVN_VER_OUTPUT}" PARENT_SCOPE) return() endif() set(${_RESULT} "" PARENT_SCOPE) endfunction() _find_workspace_directory(BAZEL_WORKSPACE_DIR) if(BAZEL_WORKSPACE_DIR) include("${BAZEL_WORKSPACE_DIR}/Workspace.cmake") endif()