ign-cmake-ignition-cmake2_2.10.0/ 0000775 0001750 0001750 00000000000 14160533245 016414 5 ustar jrivero jrivero ign-cmake-ignition-cmake2_2.10.0/cmake/ 0000775 0001750 0001750 00000000000 14160533245 017474 5 ustar jrivero jrivero ign-cmake-ignition-cmake2_2.10.0/cmake/FindTINYXML2.cmake 0000664 0001750 0001750 00000003512 14160533245 022526 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 tinyxml2. Only debian distributions package tinyxml with a pkg-config.
include(IgnPkgConfig)
# Use pkg_check_modules to start
ign_pkg_check_modules_quiet(TINYXML2 tinyxml2)
# If that failed, then fall back to manual detection (necessary for MacOS)
if(NOT TINYXML2_FOUND)
if(NOT TINYXML2_FIND_QUIETLY)
message(STATUS "Attempting manual search for tinyxml2")
endif()
find_path(TINYXML2_INCLUDE_DIRS tinyxml2.h ${TINYXML2_INCLUDE_DIRS} ENV CPATH)
find_library(TINYXML2_LIBRARIES NAMES tinyxml2)
set(TINYXML2_FOUND true)
if(NOT TINYXML2_INCLUDE_DIRS)
if(NOT TINYXML2_FIND_QUIETLY)
message(STATUS "Looking for tinyxml2 headers - not found")
endif()
set(TINYXML2_FOUND false)
endif()
if(NOT TINYXML2_LIBRARIES)
if(NOT TINYXML2_FIND_QUIETLY)
message (STATUS "Looking for tinyxml2 library - not found")
endif()
set(TINYXML2_FOUND false)
endif()
if(TINYXML2_FOUND)
include(IgnImportTarget)
ign_import_target(TINYXML2)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
TINYXML2
REQUIRED_VARS TINYXML2_FOUND)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/pkgconfig/ 0000775 0001750 0001750 00000000000 14160533245 021443 5 ustar jrivero jrivero ign-cmake-ignition-cmake2_2.10.0/cmake/pkgconfig/ignition.pc.in 0000664 0001750 0001750 00000001201 14160533245 024206 0 ustar jrivero jrivero prefix=${pcfiledir}/@PC_CONFIG_RELATIVE_PATH_TO_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@IGN_INCLUDE_INSTALL_DIR_POSTFIX@
Name: Ignition @IGN_DESIGNATION@
Description: A set of @IGN_DESIGNATION@ classes for robot applications
Version: @PROJECT_VERSION_FULL_NO_SUFFIX@
Requires: ignition-cmake@IGNITION_CMAKE_VERSION_MAJOR@ >= 1.1 @PROJECT_PKGCONFIG_REQUIRES@
Requires.private: @PROJECT_PKGCONFIG_REQUIRES_PRIVATE@
Libs: -L${libdir} @project_pkgconfig_core_lib@ @PROJECT_PKGCONFIG_LIBS@
Libs.private: @PROJECT_PKGCONFIG_LIBS_PRIVATE@
CFlags: -I${includedir} @PROJECT_PKGCONFIG_CFLAGS@
ign-cmake-ignition-cmake2_2.10.0/cmake/pkgconfig/ignition-component.pc.in 0000664 0001750 0001750 00000001262 14160533245 026215 0 ustar jrivero jrivero prefix=${pcfiledir}/@PC_CONFIG_RELATIVE_PATH_TO_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@IGN_INCLUDE_INSTALL_DIR_POSTFIX@
Name: Ignition @IGN_DESIGNATION@ @component_name@
Description: A set of @IGN_DESIGNATION@ @component_name@ classes for robot applications
Version: ignition-cmake@IGNITION_CMAKE_VERSION_MAJOR@ >= 1.1 @PROJECT_VERSION_FULL_NO_SUFFIX@
Requires: @component_pkgconfig_requires@
Requires.private: @component_pkgconfig_requires_private@
Libs: -L${libdir} @component_pkgconfig_lib@ @component_pkgconfig_lib_deps@
Libs.private: @component_pkgconfig_lib_deps_private@
CFLags: -I${includedir} @component_pkgconfig_cflags@
ign-cmake-ignition-cmake2_2.10.0/cmake/version_info.json.in 0000664 0001750 0001750 00000002330 14160533245 023472 0 ustar jrivero jrivero {
"build":
{
"cmake_build_type": "${CMAKE_BUILD_TYPE}",
"build_time": "${build_time}",
"platform":
{
"hostname": "${HOST}",
"fqdn": "${FQDN}",
"memory":
{
"total_virtual": "${TOTAL_VIRTUAL}",
"available_virtual": "${AVAILABLE_VIRTUAL}",
"total_physical": "${TOTAL_PHYSICAL}",
"available_physical": "${AVAILABLE_PHYSICAL}"
},
"processor":
{
"name": "${PROC_NAME}",
"description": "${PROC_DESC}",
"serial_number": "${PROC_SERIAL}",
"number_of_logical_cores": "${NUM_LOGICAL}",
"number_of_physical_cores": "${NUM_PHYSICAL}"
},
"os":
{
"name": "${OS_NAME}",
"release": "${OS_RELEASE}",
"version": "${OS_VERSION}",
"platform": "${OS_PLATFORM}"
}
}
},
"hg":
{
"hash": "${HG_GLOBAL_REVISION}",
"revision_number": "${HG_REVISION_NUM}",
"branch": "${HG_BRANCH}"
},
"ignition":
{
"project_name": "${PROJECT_NAME}",
"version": "${PROJECT_VERSION}",
"version_full": "${PROJECT_VERSION_FULL}",
"major": "${PROJECT_VERSION_MAJOR}",
"minor": "${PROJECT_VERSION_MINOR}",
"patch": "${PROJECT_VERSION_PATCH}"
}
}
ign-cmake-ignition-cmake2_2.10.0/cmake/FindIFADDRS.cmake 0000664 0001750 0001750 00000002361 14160533245 022355 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 ifaddrs
# If we cannot find the header or the library, we will switch this to false
set(IFADDRS_FOUND true)
# Find ifaddrs.h
find_path(IFADDRS_INCLUDE_DIRS ifaddrs.h)
if(NOT IFADDRS_INCLUDE_DIRS)
set(IFADDRS_FOUND false)
endif()
if(IFADDRS_FOUND)
include(IgnImportTarget)
# Since this is a header-only library, we should import it as an INTERFACE
# target.
ign_import_target(IFADDRS INTERFACE)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
IFADDRS
REQUIRED_VARS IFADDRS_FOUND)
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnCreateDocs.cmake 0000664 0001750 0001750 00000020300 14160533245 023143 0 ustar jrivero jrivero #.rst
# IgnCreatePackage
# ----------------
#
# ign_create_docs
#
# Creates documentation for an ignition library project.
#
#===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#################################################
# ign_create_docs(
# [API_MAINPAGE_MD ]
# [AUTOGENERATED_DOC ]
# [TUTORIALS_MAINPAGE_MD ]
# [ADDITIONAL_INPUT_DIRS ]
# [TAGFILES ])
#
# This function will configure doxygen templates and install them.
#
# API_MAINPAGE_MD: Optional. Specify a Markdown page to use as the main page
# for API documentation.
# AUTOGENERATED_DOC: Optional. Directory with the generated code.
# TUTORIALS_MAINPAGE_MD: Optional. Specify a Markdown page to use as the
# main page for tutorial documentation.
# ADDITIONAL_INPUT_DIRS: Optional. Specify additional input directories to parse when generating documentation.
# IMAGE_PATH_DIRS: Optional. Specify additional input directories where images are located
# TAGFILES: Optional. Specify tagfiles for doxygen to use. It should be a list of strings like:
# "${IGNITION-_DOXYGEN_TAGFILE} = ${IGNITION-_API_URL}"
function(ign_create_docs)
#------------------------------------
# Define the expected arguments
set(options)
set(oneValueArgs API_MAINPAGE_MD AUTOGENERATED_DOC TUTORIALS_MAINPAGE_MD)
set(multiValueArgs "TAGFILES" "ADDITIONAL_INPUT_DIRS" "IMAGE_PATH_DIRS")
option(BUILD_DOCS "Build docs" ON)
if (NOT ${BUILD_DOCS})
message(STATUS "Building Documentation disabled via BUILD_DOCS=OFF")
return()
endif()
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_create_docs "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(required_html_files
"doxygen/html/annotated.html"
"doxygen/html/classes.html"
"doxygen/html/files.html"
"doxygen/html/functions.html"
"doxygen/html/functions_func.html"
"doxygen/html/functions_vars.html"
"doxygen/html/functions_type.html"
"doxygen/html/functions_enum.html"
"doxygen/html/functions_eval.html"
"doxygen/html/hierarchy.html"
"doxygen/html/index.html"
"doxygen/html/namespaces.html"
"doxygen/html/namespacemembers.html"
"doxygen/html/namespacemembers_func.html"
"doxygen/html/namespacemembers_type.html"
"doxygen/html/namespacemembers_vars.html"
"doxygen/html/namespacemembers_enum.html"
"doxygen/html/namespacemembers_eval.html"
)
# Add an html file for each required_html_files, which guarantees that
# all the links in header.html are valid. This is needed because
# doxygen does not generate an html file if the necessary content is not
# present in a project. For example, the "hierarchy.html" may not be
# generated in a project that has no class hierarchy.
file(READ "${IGNITION_CMAKE_DOXYGEN_DIR}/header.html" doxygen_header)
file(READ "${IGNITION_CMAKE_DOXYGEN_DIR}/footer.html" doxygen_footer)
string(REGEX REPLACE "\\$projectname" "Ignition ${IGN_DESIGNATION_CAP}"
doxygen_header ${doxygen_header})
string(REGEX REPLACE "\\$projectnumber" "${PROJECT_VERSION_FULL}"
doxygen_header ${doxygen_header})
string(REGEX REPLACE "\\$title" "404"
doxygen_header ${doxygen_header})
foreach(required_file ${required_html_files})
file(WRITE ${CMAKE_BINARY_DIR}/${required_file} ${doxygen_header})
file(APPEND ${CMAKE_BINARY_DIR}/${required_file}
"
No Documentation
This library does not contain the selected type of documentation.
")
file(APPEND ${CMAKE_BINARY_DIR}/${required_file} ${doxygen_footer})
endforeach()
#--------------------------------------
# Configure documentation uploader
configure_file("${IGNITION_CMAKE_DIR}/upload_doc.sh.in"
${CMAKE_BINARY_DIR}/upload_doc.sh @ONLY)
#--------------------------------------
# Create man pages
include(IgnRonn2Man)
ign_add_manpage_target()
set(IGNITION_DOXYGEN_API_MAINPAGE_MD ${ign_create_docs_API_MAINPAGE_MD})
set(IGNITION_DOXYGEN_AUTOGENERATED_DOC ${ign_create_docs_AUTOGENERATED_DOC})
set(IGNITION_DOXYGEN_TUTORIALS_MAINPAGE_MD
${ign_create_docs_TUTORIALS_MAINPAGE_MD})
set(IGNITION_DOXYGEN_TAGFILES " ")
foreach(tagfile ${ign_create_docs_TAGFILES})
ign_string_append(IGNITION_DOXYGEN_TAGFILES "\"${tagfile}\"" DELIM " \\\\\\\\\n ")
endforeach()
set(IGNITION_DOXYGEN_ADDITIONAL_INPUT_DIRS " ")
foreach(dir ${ign_create_docs_ADDITIONAL_INPUT_DIRS})
ign_string_append(IGNITION_DOXYGEN_ADDITIONAL_INPUT_DIRS "${dir}")
endforeach()
set(IGNITION_DOXYGEN_IMAGE_PATH " ")
foreach(dir ${ign_create_docs_IMAGE_PATH_DIRS})
ign_string_append(IGNITION_DOXYGEN_IMAGE_PATH "${dir}")
endforeach()
find_package(Doxygen)
if (DOXYGEN_FOUND AND EXISTS ${IGNITION_CMAKE_DOXYGEN_DIR}/api.in)
if(EXISTS ${CMAKE_SOURCE_DIR}/tutorials)
set(IGNITION_DOXYGEN_TUTORIALS_DIR ${CMAKE_SOURCE_DIR}/tutorials)
else()
set(IGNITION_DOXYGEN_TUTORIALS_DIR "")
endif()
# Configure the main API+Tutorials doxygen configuration file. This
# configuration file is not used to generate the doxygen tag file,
# see below.
set(IGNITION_DOXYGEN_GENHTML "YES")
# Be careful when manipulating IGNITION_DOXYGEN_INPUT. Doxygen is finicky
# about the spaces between input files/directories. If you put each cmake
# variable on a separate line to make this `set` command more readable,
# then doxygen will not generate the correct/complete output.
set(IGNITION_DOXYGEN_INPUT "${IGNITION_DOXYGEN_API_MAINPAGE_MD} ${IGNITION_DOXYGEN_AUTOGENERATED_DOC} ${IGNITION_DOXYGEN_TUTORIALS_DIR} ${IGNITION_DOXYGEN_TUTORIALS_MAINPAGE_MD} ${ign_doxygen_component_input_dirs} ${IGNITION_DOXYGEN_ADDITIONAL_INPUT_DIRS}")
configure_file(${IGNITION_CMAKE_DOXYGEN_DIR}/api.in
${CMAKE_BINARY_DIR}/api.dox @ONLY)
# The doxygen tagfile should not contain tutorial information. If tutorial
# information is included in the tagfile and a downstream package also has
# a page called "tutorials", then doxygen will silently fail to generate
# tutorial content for the downstream package. In order to
# satisfy this constraint we generate another doxygen configuration file
# whose sole purpose is the generation of a project's doxygen tagfile that
# contains only API information.
set(IGNITION_DOXYGEN_GENHTML "NO")
set(IGNITION_DOXYGEN_GENTAGFILE
"${CMAKE_BINARY_DIR}/${PROJECT_NAME_LOWER}.tag.xml")
set(IGNITION_DOXYGEN_INPUT "${ign_doxygen_component_input_dirs} ${IGNITION_DOXYGEN_AUTOGENERATED_DOC}")
configure_file(${IGNITION_CMAKE_DOXYGEN_DIR}/api.in
${CMAKE_BINARY_DIR}/api_tagfile.dox @ONLY)
add_custom_target(doc ALL
# Generate the API tagfile
${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/api_tagfile.dox
# Generate the API documentation
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/api.dox
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM)
install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME_LOWER}.tag.xml
DESTINATION ${IGN_DATA_INSTALL_DIR})
endif()
#--------------------------------------
# If we're configuring only to build docs, stop here
if (DOC_ONLY)
message(WARNING "Configuration was done in DOC_ONLY mode."
" You can build documentation (make doc), but nothing else.")
return()
endif()
endfunction()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnSetCompilerFlags.cmake 0000664 0001750 0001750 00000034452 14160533245 024347 0 ustar jrivero jrivero #.rst
# IgnSetCompilerFlags
# -------------------
#
# ign_set_compiler_flags()
#
# Sets up compiler flags for an ignition library project
#
#===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#
#################################################
# Set up compiler flags
macro(ign_set_compiler_flags)
option(USE_IGN_RECOMMENDED_FLAGS "Build project using the compiler flags recommended by the ignition developers" ON)
if(MSVC)
ign_setup_msvc()
elseif(UNIX)
ign_setup_unix()
endif()
if(APPLE)
ign_setup_apple()
endif()
# Check if we are compiling with Clang and cache it
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CLANG true)
endif()
# Check if we are compiling with GCC and cache it
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(GCC true)
endif()
# GCC and Clang use many of the same compilation flags, so it might be useful
# to have a variable that indicates if one of them is being used.
if(GCC OR CLANG)
set(GCC_OR_CLANG true)
endif()
if(GCC_OR_CLANG)
if(USE_IGN_RECOMMENDED_FLAGS)
ign_setup_gcc_or_clang()
endif()
option(USE_HOST_SSE_FLAGS "Explicitly use compiler flags to indicate the SSE version of the host machine" TRUE)
if(USE_HOST_SSE_FLAGS)
ign_set_sse_flags()
endif()
endif()
endmacro()
#################################################
# Configure settings for Unix
macro(ign_setup_unix)
find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin )
if(CMAKE_UNAME)
exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR} CACHE INTERNAL
"processor type (i386 and x86_64)")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
set(IGN_ADD_fPIC_TO_LIBRARIES true)
endif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
endif(CMAKE_UNAME)
endmacro()
#################################################
macro(ign_setup_apple)
# NOTE MacOSX provides different system versions than CMake is parsing.
# The following table lists the most recent OSX versions
# 9.x.x = Mac OSX Leopard (10.5)
# 10.x.x = Mac OSX Snow Leopard (10.6)
# 11.x.x = Mac OSX Lion (10.7)
# 12.x.x = Mac OSX Mountain Lion (10.8)
if(${CMAKE_SYSTEM_VERSION} LESS 10)
add_definitions(-DMAC_OS_X_VERSION=1050)
elseif(${CMAKE_SYSTEM_VERSION} GREATER 10 AND ${CMAKE_SYSTEM_VERSION} LESS 11)
add_definitions(-DMAC_OS_X_VERSION=1060)
elseif(${CMAKE_SYSTEM_VERSION} GREATER 11 AND ${CMAKE_SYSTEM_VERSION} LESS 12)
add_definitions(-DMAC_OS_X_VERSION=1070)
elseif(${CMAKE_SYSTEM_VERSION} GREATER 12 OR ${CMAKE_SYSTEM_VERSION} EQUAL 12)
add_definitions(-DMAC_OS_X_VERSION=1080)
# Use libc++ on Mountain Lion (10.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
else()
add_definitions(-DMAC_OS_X_VERSION=0)
endif()
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined -Wl,dynamic_lookup")
endmacro()
#################################################
# Set up compilation flags for GCC or Clang
macro(ign_setup_gcc_or_clang)
if(ign_configure_build_HIDE_SYMBOLS_BY_DEFAULT)
set(CMAKE_C_VISIBILITY_PRESET "hidden")
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
else()
set(CMAKE_C_VISIBILITY_PRESET "default")
set(CMAKE_CXX_VISIBILITY_PRESET "default")
endif()
ign_filter_valid_compiler_options(
CUSTOM_ALL_FLAGS
-Wall -Wextra -Wno-long-long -Wno-unused-value -Wfloat-equal
-Wshadow -Winit-self -Wswitch-default -Wmissing-include-dirs -pedantic
)
# -ggdb3: Produce comprehensive debug information that can be utilized by gdb
set(CUSTOM_DEBUG_FLAGS "-ggdb3")
# We use the default flags for Release
set(CUSTOM_RELEASE_FLAGS "")
# -UNDEBUG: Undefine the NDEBUG symbol so that assertions get triggered in
# RelWithDebInfo mode
# NOTE: Always make -UNDEBUG the first flag in this list so that it appears
# immiediately after cmake's automatically provided -DNDEBUG flag.
# Keeping them next to each other should make it more clear that the
# -DNDEBUG flag is being canceled out.
set(CUSTOM_RELWITHDEBINFO_FLAGS "-UNDEBUG")
# We use the default flags for MinSizeRel
set(CUSTOM_MINSIZEREL_FLAGS "")
# -fno-omit-frame-pointer: TODO Why do we use this?
# -g: Produce debug information
# -pg: Produce information that is helpful for the gprof profiling tool
set(CUSTOM_PROFILE_FLAGS "-fno-omit-frame-pointer -g -pg")
# -g: Produce debug information.
# -O0: Do absolutely no performance optimizations and reduce compilation time.
# -Wformat=2: Print extra warnings for string formatting functions.
# --coverage: Tell the compiler that we want our build to be instrumented for
# coverage analysis.
# -fno-inline: Prevent the compiler from inlining functions. Inlined functions
# may confuse the coverage analysis.
set(CUSTOM_C_COVERAGE_FLAGS "-g -O0 -Wformat=2 --coverage -fno-inline")
set(CUSTOM_CXX_COVERAGE_FLAGS "${CUSTOM_C_COVERAGE_FLAGS}")
# We add these flags depending on whether the compiler can support them,
# because they cause errors when compiling with Clang.
# -fno-elide-constructors: Prevent the compiler from eliding constructors.
# Elision may confuse the coverage analysis.
# -fno-default-inline: Prevent class members that are defined inside of their
# class definition from automatically being marked as
# inline functions.
# ...TODO: Is this redundant with -fno-inline?
# -fno-implicit-inline-templates: TODO: Why do we use this?
ign_filter_valid_compiler_options(
CUSTOM_CXX_COVERAGE_FLAGS
-fno-elide-constructors
-fno-default-inline
-fno-implicit-inline-templates)
# NOTE We do not use the CACHE argument when appending flags to these
# variables, because appending to the CACHE will make these variables grow
# with redundant flags each time cmake is run. By not using CACHE, we create
# "local" copies of each of these variables, so they will not be preserved
# between runs of cmake. However, since these "local" variables are created in
# the top-level scope, they will be visible to all subdirectories in our
# filesystem, making them effectively global.
# NOTE These flags are being specified in a very particular order. First, we
# specify the original set of flags, then we specify the set of flags which
# are being passed to all build types, then we specify the set of flags which
# are specific to each build type. When contradictory flags are given to a
# compiler, whichever flag was specified last gets precedence. Therefore, we
# want the flags that we're passing in now to have precedence over the
# original flags for each build type, and we want the flags that are specific
# to each build type to have precedence over the flags that are passed to all
# build types, to make sure that each build type can customize its flags
# without any conflicts.
# cmake automatically provides -g for *_FLAGS_DEBUG
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CUSTOM_ALL_FLAGS} ${CUSTOM_DEBUG_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${CUSTOM_ALL_FLAGS} ${CUSTOM_DEBUG_FLAGS}")
# cmake automatically provides -O3 and -DNDEBUG for *_FLAGS_RELEASE
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${CUSTOM_RELEASE_FLAGS} ${CUSTOM_ALL_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${CUSTOM_ALL_FLAGS} ${CUSTOM_RELEASE_FLAGS}")
# cmake automatically provides -g, -O2, and -DNDEBUG for *_FLAGS_RELWITHDEBINFO
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CUSTOM_ALL_FLAGS} ${CUSTOM_RELWITHDEBINFO_FLAGS}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${CUSTOM_ALL_FLAGS} ${CUSTOM_RELWITHDEBINFO_FLAGS}")
# cmake automatically provides -Os and -DNDEBUG for *_FLAGS_MINSIZEREL
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} ${CUSTOM_ALL_FLAGS} ${CUSTOM_MINSIZEREL_FLAGS}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${CUSTOM_ALL_FLAGS} ${CUSTOM_MINSIZEREL_FLAGS}")
# NONE is a custom type used in Debian, not automatically provided by cmake
set(CMAKE_C_FLAGS_NONE "${CMAKE_C_FLAGS_NONE} ${CUSTOM_ALL_FLAGS} ${MSVC_MINIMAL_FLAGS}")
set(CMAKE_CXX_FLAGS_NONE "${CMAKE_CXX_FLAGS_NONE} ${CUSTOM_ALL_FLAGS} ${MSVC_MINIMAL_FLAGS}")
# PROFILE is a custom build type, not automatically provided by cmake
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE} ${CUSTOM_ALL_FLAGS} ${CUSTOM_PROFILE_FLAGS}")
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_PROFILE} ${CUSTOM_ALL_FLAGS} ${CUSTOM_PROFILE_FLAGS}")
# COVERAGE is a custom build type, not automatically provided by cmake
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE} ${CUSTOM_ALL_FLAGS} ${CUSTOM_C_COVERAGE_FLAGS}")
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} ${CUSTOM_ALL_FLAGS} ${CUSTOM_CXX_COVERAGE_FLAGS}")
# NOTE: Leave CMAKE_C_FLAGS and CMAKE_CXX_FLAGS blank, because those will
# be appended to all build configurations.
endmacro()
#################################################
# Identify what type of Streaming SIMD Extension is being used by the system and
# then set the compiler's SSE flags appropriately.
macro(ign_set_sse_flags)
message(STATUS "\n-- Searching for host SSE information")
include(IgnCheckSSE)
if(SSE2_FOUND)
add_compile_options(-msse -msse2)
if (NOT APPLE)
add_compile_options(-mfpmath=sse)
message(STATUS "SSE2 found")
endif()
endif()
if(SSE3_FOUND)
add_compile_options(-msse3)
message(STATUS "SSE3 found")
endif()
if (SSSE3_FOUND)
add_compile_options(-mssse3)
endif()
if (SSE4_1_FOUND OR SSE4_2_FOUND)
if (SSE4_1_FOUND)
add_compile_options(-msse4.1)
message(STATUS "SSE4.1 found")
endif()
if (SSE4_2_FOUND)
add_compile_options(-msse4.2)
message(STATUS "SSE4.2 found")
endif()
else()
message(STATUS "SSE4 disabled.\n--")
endif()
endmacro()
#################################################
# Set up compilation flags for Microsoft Visual Studio/C++
macro(ign_setup_msvc)
# Reduce overhead by ignoring unnecessary Windows headers
add_definitions(-DWIN32_LEAN_AND_MEAN)
# Don't pull in the Windows min/max macros
add_definitions(-DNOMINMAX)
if(USE_IGN_RECOMMENDED_FLAGS)
# Gy: Prevent errors caused by multiply-defined symbols
# W2: Warning level 2: significant warnings.
# TODO: Recommend Wall in the future.
# Note: MSVC /Wall generates tons of warnings on gtest code.
set(MSVC_MINIMAL_FLAGS "/Gy /W2")
# Zi: Produce complete debug information
# Note: We provide Zi to ordinary release mode because it does not impact
# performance and can be helpful for debugging.
set(MSVC_DEBUG_FLAGS "${MSVC_MINIMAL_FLAGS} /Zi")
# GL: Enable Whole Program Optimization
set(MSVC_RELEASE_FLAGS "${MSVC_DEBUG_FLAGS} /GL")
# UNDEBUG: Undefine NDEBUG so that assertions can be triggered
set(MSVC_RELWITHDEBINFO_FLAGS "${MSVC_RELEASE_FLAGS} /UNDEBUG")
# INCREMENTAL:NO fix LNK4075 warning
set(MSVC_RELWITHDEBINFO_LINKER_FLAGS "/INCREMENTAL:NO")
# cmake automatically provides /Zi /Ob0 /Od /RTC1
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MSVC_DEBUG_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MSVC_DEBUG_FLAGS}")
# cmake automatically provides /O2 /Ob2 /DNDEBUG
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MSVC_RELEASE_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MSVC_RELEASE_FLAGS}")
# cmake automatically provides /Zi /O2 /Ob1 /DNDEBUG
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${MSVC_RELWITHDEBINFO_FLAGS}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${MSVC_RELWITHDEBINFO_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} ${MSVC_RELWITHDEBINFO_LINKER_FLAGS}")
# cmake automatically provides /O1 /Ob1 /DNDEBUG
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} ${MSVC_MINIMAL_FLAGS}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${MSVC_MINIMAL_FLAGS}")
# NOTE: Leave CMAKE_C_FLAGS and CMAKE_CXX_FLAGS blank, because
# those will be appended to all build configurations.
# TODO: What flags should be set for PROFILE and COVERAGE build types?
# Is it even possible to generate those build types on Windows?
endif()
# Use the dynamically loaded run-time library in Windows by default. The
# dynamically loaded run-time allows dynamically allocated objects to be
# passed between different DLLs, which is important for our plugin-based
# framework.
#
# In some cases, a user might want to compile with the static runtime. This
# should ONLY be done if they do not intend to use the ignition library as
# part of a plugin-based framework.
option(IGN_USE_STATIC_RUNTIME "Use the static runtime (strongly discouraged)" OFF)
if(BUILD_SHARED_LIBS)
# Users should not choose the static runtime unless they are compiling a
# static library, so we completely disable this option if BUILD_SHARED_LIBS
# is turned on.
set(IGN_USE_STATIC_RUNTIME OFF CACHE BOOL "Use the static runtime (strongly discouraged)" FORCE)
endif()
if(IGN_USE_STATIC_RUNTIME)
foreach(build_type DEBUG RELEASE RELWITHDEBINFO MINSIZEREL NONE)
foreach(lang C CXX)
set(flags_var CMAKE_${lang}_FLAGS_${build_type})
string(REGEX REPLACE "/MD" "/MT" ${flags_var} "${${flags_var}}")
endforeach()
endforeach()
endif()
# We always want this flag to be specified so we get standard-compliant
# exception handling.
# EHsc: Use standard-compliant exception handling
add_compile_options("/EHsc")
endmacro()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindAVDEVICE.cmake 0000664 0001750 0001750 00000003646 14160533245 022476 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 AV device.
set(av_major ${AVDEVICE_FIND_VERSION_MAJOR})
set(av_minor ${AVDEVICE_FIND_VERSION_MINOR})
set(av_patch ${AVDEVICE_FIND_VERSION_PATCH})
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(AVDEVICE "libavdevice >= ${av_major}.${av_minor}.${av_patch}")
if(NOT AVDEVICE_FOUND)
include(IgnManualSearch)
ign_manual_search(AVDEVICE
HEADER_NAMES "libavdevice/avdevice.h"
LIBRARY_NAMES "avdevice")
# Version check
if(AVDEVICE_FOUND)
file(READ "${AVDEVICE_INCLUDE_DIRS}/libavdevice/version.h" ver_file)
string(REGEX MATCH "LIBAVDEVICE_VERSION_MAJOR[ \t\r\n]+([0-9]*)" _ ${ver_file})
set(ver_major ${CMAKE_MATCH_1})
string(REGEX MATCH "LIBAVDEVICE_VERSION_MINOR[ \t\r\n]+([0-9]*)" _ ${ver_file})
set(ver_minor ${CMAKE_MATCH_1})
string(REGEX MATCH "LIBAVDEVICE_VERSION_MICRO[ \t\r\n]+([0-9]*)" _ ${ver_file})
set(ver_patch ${CMAKE_MATCH_1})
set(AVDEVICE_VERSION "${ver_major}.${ver_minor}.${ver_patch}")
if(AVDEVICE_VERSION VERSION_LESS AVDEVICE_FIND_VERSION)
set(AVDEVICE_FOUND FALSE)
endif()
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
AVDEVICE
REQUIRED_VARS AVDEVICE_FOUND) ign-cmake-ignition-cmake2_2.10.0/cmake/ignition-component-config.cmake.in 0000664 0001750 0001750 00000010353 14160533245 026170 0 ustar jrivero jrivero # - Config file for the @component_pkg_name@ component
#
# This should only be invoked by @PKG_NAME@-config.cmake.
#
# To load this component into your project, use:
# find_package(@PKG_NAME@ COMPONENTS @component_name@)
#
# This creates the following targets:
#
# Component library target - @import_target_name@
# Alternative target name - @simple_import_name@
# Core library + all requested components - @ign_namespace@requested
#
# Use target_link_libraries() to link your library or executable to one of the
# above targets.
#
# We also provide the following variable for backwards compatibility, but use of
# this is discouraged:
#
# @component_pkg_name@_LIBRARY - Component library (actually contains @simple_import_name@)
#
# We will also set @component_pkg_name@_FOUND to indicate that the component was found.
#
################################################################################
# We explicitly set the desired cmake version to ensure that the policy settings
# of users or of toolchains do not result in the wrong behavior for our modules.
# Note that the call to find_package(~) will PUSH a new policy stack before
# taking on these version settings, and then that stack will POP after the
# find_package(~) has exited, so this will not affect the cmake policy settings
# of a caller.
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
if(@component_pkg_name@_CONFIG_INCLUDED)
return()
endif()
set(@component_pkg_name@_CONFIG_INCLUDED TRUE)
if(NOT @component_pkg_name@_FIND_QUIETLY)
message(STATUS "Looking for @component_pkg_name@ -- found version @PROJECT_VERSION_FULL@")
endif()
@PACKAGE_INIT@
# Get access to the find_dependency utility
include(CMakeFindDependencyMacro)
# Find ignition-cmake, because we need its modules in order to find the rest of
# our dependencies.
find_dependency(ignition-cmake@IGNITION_CMAKE_VERSION_MAJOR@)
# Set the REQUIRED flag for the find_package(~) calls on this component's
# dependencies.
if(@component_pkg_name@_FIND_REQUIRED)
set(ign_package_required REQUIRED)
else()
set(ign_package_required "")
endif()
# Set the QUIET flag for the find_package(~) calls on this component's
# dependencies.
if(@component_pkg_name@_FIND_QUIETLY)
set(ign_package_quiet QUIET)
else()
set(ign_package_quiet "")
endif()
# --------------------------------
# Find the dependencies that are specific to this component (if nothing is
# below, then the component has no additional dependencies). We use
# find_package(~) instead of find_dependency(~) here so that we can support
# COMPONENT arguments.
#
# TODO: When we migrate to cmake-3.9+, change these to find_dependency(~),
# because at that point the find_dependency(~) function will support
# the COMPONENT argument.
if(NOT @component_pkg_name@_FIND_QUIETLY)
message(STATUS "Searching for dependencies of @component_pkg_name@")
endif()
@component_cmake_dependencies@
# --------------------------------
if(NOT TARGET @import_target_name@)
include("${CMAKE_CURRENT_LIST_DIR}/@target_output_filename@")
# Create a simplified imported target name for the @component@ library.
# You can link to this target instead of the @component@ library.
add_library(@simple_import_name@ INTERFACE IMPORTED)
set_target_properties(@simple_import_name@ PROPERTIES
INTERFACE_LINK_LIBRARIES "@import_target_name@")
# Note: In a future version of cmake, we can replace this with an ALIAS target
endif()
# Create the "requested" target if it does not already exist
if(NOT TARGET @ign_namespace@requested)
add_library(@ign_namespace@requested INTERFACE IMPORTED)
endif()
# Link the @component@ library to the "requested" target
get_target_property(ign_requested_components @ign_namespace@requested INTERFACE_LINK_LIBRARIES)
if(NOT ign_requested_components)
set_target_properties(@ign_namespace@requested PROPERTIES
INTERFACE_LINK_LIBRARIES "@import_target_name@")
else()
set_target_properties(@ign_namespace@requested PROPERTIES
INTERFACE_LINK_LIBRARIES "${ign_requested_components};@import_target_name@")
endif()
set(@component_pkg_name@_LIBRARY @import_target_name@)
# This macro is used by ignition-cmake to automatically configure the pkgconfig
# files for ignition projects.
ign_pkg_config_entry(@component_pkg_name@ "@component_pkg_name@")
ign-cmake-ignition-cmake2_2.10.0/cmake/FindIgnBullet.cmake 0000664 0001750 0001750 00000003115 14160533245 023164 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2019 Open Source Robotics Foundation
#
# Licensed 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.
#
########################################
# Copyright (c) 2011-2019, The DART development contributors
# All rights reserved.
#
# The list of contributors can be found at:
# https://github.com/dartsim/dart/blob/master/LICENSE
#
# This file is provided under the "BSD-style" License
########################################
set(ign_quiet_arg)
if(IgnBullet_FIND_QUIETLY)
set(ign_quiet_arg QUIET)
endif()
# Bullet. Force MODULE mode to use the FindBullet.cmake file distributed with
# CMake. Otherwise, we may end up using the BulletConfig.cmake file distributed
# with Bullet, which uses relative paths and may break transitive dependencies.
find_package(Bullet MODULE ${ign_quiet_arg})
set(IgnBullet_FOUND false)
# create Bullet target
if(BULLET_FOUND)
set(IgnBullet_FOUND true)
ign_import_target(IgnBullet
TARGET_NAME IgnBullet::IgnBullet
LIB_VAR BULLET_LIBRARIES
INCLUDE_VAR BULLET_INCLUDE_DIRS
)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnCheckSSE.cmake 0000664 0001750 0001750 00000027456 14160533245 022542 0 ustar jrivero jrivero # Copyright (c) 2012 Petroules Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer. Redistributions in binary
# form must reproduce the above copyright notice, this list of conditions and
# the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Modified for ignition libraries - 2017
# Based on the Qt 5 processor detection code, so should be very accurate
# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h
# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64)
# Regarding POWER/PowerPC, just as is noted in the Qt source,
# "There are many more known variants/revisions that we do not handle/detect."
set(archdetect_c_code "
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)
#if defined(__ARM_ARCH_7__) \\
|| defined(__ARM_ARCH_7A__) \\
|| defined(__ARM_ARCH_7R__) \\
|| defined(__ARM_ARCH_7M__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
#error cmake_ARCH armv7
#elif defined(__ARM_ARCH_6__) \\
|| defined(__ARM_ARCH_6J__) \\
|| defined(__ARM_ARCH_6T2__) \\
|| defined(__ARM_ARCH_6Z__) \\
|| defined(__ARM_ARCH_6K__) \\
|| defined(__ARM_ARCH_6ZK__) \\
|| defined(__ARM_ARCH_6M__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
#error cmake_ARCH armv6
#elif defined(__ARM_ARCH_5TEJ__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
#error cmake_ARCH armv5
#else
#error cmake_ARCH arm
#endif
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
#error cmake_ARCH i386
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
#error cmake_ARCH x86_64
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
#error cmake_ARCH ia64
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|| defined(_M_MPPC) || defined(_M_PPC)
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
#error cmake_ARCH ppc64
#else
#error cmake_ARCH ppc
#endif
#endif
#error cmake_ARCH unknown
")
# Set ppc_support to TRUE before including this file or ppc and ppc64
# will be treated as invalid architectures since they are no longer supported by Apple
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
# On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set
# First let's normalize the order of the values
# Note that it's not possible to compile PowerPC applications if you are using
# the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
# disable it by default
# See this page for more information:
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
set(osx_arch_ppc TRUE)
elseif("${osx_arch}" STREQUAL "i386")
set(osx_arch_i386 TRUE)
elseif("${osx_arch}" STREQUAL "x86_64")
set(osx_arch_x86_64 TRUE)
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
set(osx_arch_ppc64 TRUE)
else()
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
endif()
endforeach()
# Now add all the architectures in our normalized order
if(osx_arch_ppc)
list(APPEND ARCH ppc)
endif()
if(osx_arch_i386)
list(APPEND ARCH i386)
endif()
if(osx_arch_x86_64)
list(APPEND ARCH x86_64)
endif()
if(osx_arch_ppc64)
list(APPEND ARCH ppc64)
endif()
else()
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
enable_language(C)
# Detect the architecture in a rather creative way...
# This compiles a small C program which is a series of ifdefs that selects a
# particular #error preprocessor directive whose message string contains the
# target architecture. The program will always fail to compile (both because
# file is not a valid C program, and obviously because of the presence of the
# #error preprocessor directives... but by exploiting the preprocessor in this
# way, we can detect the correct target architecture even when cross-compiling,
# since the program itself never needs to be run (only the compiler/preprocessor)
try_run(
run_result_unused
compile_result_unused
"${CMAKE_BINARY_DIR}"
"${CMAKE_BINARY_DIR}/arch.c"
COMPILE_OUTPUT_VARIABLE ARCH
CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
)
# Parse the architecture name from the compiler output
string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}")
# Get rid of the value marker leaving just the architecture name
string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}")
# If we are compiling with an unknown architecture this variable should
# already be set to "unknown" but in the case that it's empty (i.e. due
# to a typo in the code), then set it to unknown
if (NOT ARCH)
set(ARCH unknown)
endif()
endif()
# Check if SSE instructions are available on the machine where
# the project is compiled.
IF (ARCH MATCHES "i386" OR ARCH MATCHES "x86_64")
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO)
STRING(REGEX REPLACE "^.*(sse2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "sse2" "${SSE_THERE}" SSE2_TRUE)
IF (SSE2_TRUE)
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
ELSE (SSE2_TRUE)
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
ENDIF (SSE2_TRUE)
# /proc/cpuinfo apparently omits sse3 :(
STRING(REGEX REPLACE "^.*[^s](sse3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "sse3" "${SSE_THERE}" SSE3_TRUE)
IF (NOT SSE3_TRUE)
STRING(REGEX REPLACE "^.*(T2300).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "T2300" "${SSE_THERE}" SSE3_TRUE)
ENDIF (NOT SSE3_TRUE)
STRING(REGEX REPLACE "^.*(ssse3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "ssse3" "${SSE_THERE}" SSSE3_TRUE)
IF (SSE3_TRUE OR SSSE3_TRUE)
set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
ELSE (SSE3_TRUE OR SSSE3_TRUE)
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
ENDIF (SSE3_TRUE OR SSSE3_TRUE)
IF (SSSE3_TRUE)
set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
ELSE (SSSE3_TRUE)
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
ENDIF (SSSE3_TRUE)
STRING(REGEX REPLACE "^.*(sse4_1).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE)
IF (SSE41_TRUE)
set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
ELSE (SSE41_TRUE)
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
ENDIF (SSE41_TRUE)
STRING(REGEX REPLACE "^.*(sse4_2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "sse4_2" "${SSE_THERE}" SSE42_TRUE)
IF (SSE42_TRUE)
set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host")
ELSE (SSE42_TRUE)
set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host")
ENDIF (SSE42_TRUE)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE
CPUINFO)
STRING(REGEX REPLACE "^.*[^S](SSE2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE)
IF (SSE2_TRUE)
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
ELSE (SSE2_TRUE)
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
ENDIF (SSE2_TRUE)
STRING(REGEX REPLACE "^.*[^S](SSE3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSE3" "${SSE_THERE}" SSE3_TRUE)
IF (SSE3_TRUE)
set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
ELSE (SSE3_TRUE)
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
ENDIF (SSE3_TRUE)
STRING(REGEX REPLACE "^.*(SSSE3).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSSE3" "${SSE_THERE}" SSSE3_TRUE)
IF (SSSE3_TRUE)
set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
ELSE (SSSE3_TRUE)
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
ENDIF (SSSE3_TRUE)
STRING(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE)
IF (SSE41_TRUE)
set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
ELSE (SSE41_TRUE)
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
ENDIF (SSE41_TRUE)
STRING(REGEX REPLACE "^.*(SSE4.2).*$" "\\1" SSE_THERE ${CPUINFO})
STRING(COMPARE EQUAL "SSE4.2" "${SSE_THERE}" SSE42_TRUE)
IF (SSE42_TRUE)
set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host")
ELSE (SSE42_TRUE)
set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host")
ENDIF (SSE42_TRUE)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows")
# TODO
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host")
ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host")
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
ENDIF(ARCH MATCHES "i386" OR ARCH MATCHES "x86_64")
if(NOT SSE2_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE2 on this machine.")
endif(NOT SSE2_FOUND)
if(NOT SSE3_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE3 on this machine.")
endif(NOT SSE3_FOUND)
if(NOT SSSE3_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSSE3 on this machine.")
endif(NOT SSSE3_FOUND)
if(NOT SSE4_1_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE4.1 on this machine.")
endif(NOT SSE4_1_FOUND)
if(NOT SSE4_2_FOUND)
MESSAGE(STATUS "Could not find hardware support for SSE4.2 on this machine.")
endif(NOT SSE4_2_FOUND)
ign-cmake-ignition-cmake2_2.10.0/cmake/FindSWSCALE.cmake 0000664 0001750 0001750 00000002141 14160533245 022376 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 libswscale format
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(SWSCALE libswscale)
if(NOT SWSCALE_FOUND)
include(IgnManualSearch)
ign_manual_search(SWSCALE
HEADER_NAMES "libswscale/swscale.h"
LIBRARY_NAMES "swscale")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
SWSCALE
REQUIRED_VARS SWSCALE_FOUND)
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnConfigureProject.cmake 0000664 0001750 0001750 00000021361 14160533245 024407 0 ustar jrivero jrivero #.rst
# IgnConfigureProject
# -------------------
#
# ign_configure_project([VERSION_SUFFIX
])
#
# Sets up an ignition library project.
#
# NO_IGNITION_PREFIX: Optional. Don't use ignition as prefix in
# cmake project name.
# REPLACE_IGNITION_INCLUDE_PATH: Optional. Specify include folder
# names to replace the default value of
# ignition/${IGN_DESIGNATION}
# VERSION_SUFFIX: Optional. Specify a prerelease version suffix.
#
#===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#################################################
# Initialize the ignition project
macro(ign_configure_project)
#------------------------------------
# Define the expected arguments
set(options NO_IGNITION_PREFIX)
set(oneValueArgs REPLACE_IGNITION_INCLUDE_PATH VERSION_SUFFIX)
set(multiValueArgs) # We are not using multiValueArgs yet
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_configure_project "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# Note: The following are automatically defined by project(~) in cmake v3:
# PROJECT_NAME
# PROJECT_VERSION_MAJOR
# PROJECT_VERSION_MINOR
# PROJECT_VERSION_PATCH
if(ign_configure_project_VERSION_SUFFIX)
set(PROJECT_VERSION_SUFFIX ${ign_configure_project_VERSION_SUFFIX})
endif()
#============================================================================
# Extract the designation
#============================================================================
set(IGN_DESIGNATION ${PROJECT_NAME})
# Remove the leading "ignition-"
string(REGEX REPLACE "ignition-" "" IGN_DESIGNATION ${IGN_DESIGNATION})
# Remove the trailing version number
string(REGEX REPLACE "[0-9]+" "" IGN_DESIGNATION ${IGN_DESIGNATION})
#============================================================================
# Set project variables
#============================================================================
if(ign_configure_project_NO_IGNITION_PREFIX)
set(PROJECT_NAME_NO_VERSION ${IGN_DESIGNATION})
else()
set(PROJECT_NAME_NO_VERSION "ignition-${IGN_DESIGNATION}")
endif()
string(TOLOWER ${PROJECT_NAME_NO_VERSION} PROJECT_NAME_NO_VERSION_LOWER)
string(TOUPPER ${PROJECT_NAME_NO_VERSION} PROJECT_NAME_NO_VERSION_UPPER)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
string(TOLOWER ${IGN_DESIGNATION} IGN_DESIGNATION_LOWER)
string(TOUPPER ${IGN_DESIGNATION} IGN_DESIGNATION_UPPER)
string(SUBSTRING ${IGN_DESIGNATION} 0 1 IGN_DESIGNATION_FIRST_LETTER)
string(TOUPPER ${IGN_DESIGNATION_FIRST_LETTER} IGN_DESIGNATION_FIRST_LETTER)
string(REGEX REPLACE "^.(.*)" "${IGN_DESIGNATION_FIRST_LETTER}\\1"
IGN_DESIGNATION_CAP "${IGN_DESIGNATION}")
set(PROJECT_EXPORT_NAME ${PROJECT_NAME_LOWER})
set(PROJECT_LIBRARY_TARGET_NAME ${PROJECT_NAME_LOWER})
if(ign_configure_project_REPLACE_IGNITION_INCLUDE_PATH)
set(PROJECT_INCLUDE_DIR ${ign_configure_project_REPLACE_IGNITION_INCLUDE_PATH})
else()
set(PROJECT_INCLUDE_DIR ignition/${IGN_DESIGNATION})
endif()
# version .
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
# version ..
set(PROJECT_VERSION_FULL
${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
# The full version of the project, but without any prerelease suffix
set(PROJECT_VERSION_FULL_NO_SUFFIX ${PROJECT_VERSION_FULL})
if(PROJECT_VERSION_SUFFIX)
# Append the prerelease suffix to PROJECT_VERSION_FULL if this has a suffix
# version ..~
set(PROJECT_VERSION_FULL ${PROJECT_VERSION_FULL}~${PROJECT_VERSION_SUFFIX})
endif()
set(PKG_NAME ${PROJECT_NAME_LOWER})
message(STATUS "${PROJECT_NAME} version ${PROJECT_VERSION_FULL}")
#============================================================================
# Identify the operating system
ign_check_os()
#============================================================================
# Create package information
ign_setup_packages()
#============================================================================
# Initialize build errors/warnings
# NOTE: We no longer use CACHE for these variables because it was set to
# "INTERNAL", making it unnecessary to cache them. As long as this macro is
# called from the top-level scope, these variables will effectively be global,
# even without putting them in the cache. If this macro is not being called
# from the top-level scope, then it is being used incorrectly.
set(build_errors "")
set(build_warnings "")
#============================================================================
# Initialize the list of -config.cmake dependencies
set(PROJECT_CMAKE_DEPENDENCIES)
# Initialize the list of .pc Requires
set(PROJECT_PKGCONFIG_REQUIRES)
# Initialize the list of .pc Requires.private
set(PROJECT_PKGCONFIG_REQUIRES_PRIVATE)
# Initialize the list of .pc Libs
set(PROJECT_PKGCONFIG_LIBS)
# Initialize the list of .pc Libs.private
set(PROJECT_PKGCONFIG_LIBS_PRIVATE)
#============================================================================
# We turn off extensions because (1) we do not ever want to use non-standard
# compiler extensions, and (2) this variable is on by default, causing cmake
# to choose the flag -std=gnu++14 instead of -std=c++14 when the C++14
# features are requested. Explicitly turning this flag off will force cmake to
# choose -std=c++14.
set(CMAKE_CXX_EXTENSIONS off)
#============================================================================
# Put all runtime objects (executables and DLLs) into a single directory.
# This helps executables (e.g. tests) to run from the build directory on
# Windows. The DLLs that we build for this library needs to be available to
# the executables that depend on them.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Put all libraries (.so, static .lib) into a single directory. This is just
# for convenience.
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
# Put all archive libraries (export .lib) into the lib directory. This is
# just for convenience.
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endmacro()
#################################################
# Check the OS type.
macro(ign_check_os)
# CMake does not distinguish Linux from other Unices.
string(REGEX MATCH "Linux" PLAYER_OS_LINUX ${CMAKE_SYSTEM_NAME})
# Nor *BSD
string(REGEX MATCH "BSD" PLAYER_OS_BSD ${CMAKE_SYSTEM_NAME})
# Or Solaris. I'm seeing a trend, here
string(REGEX MATCH "SunOS" PLAYER_OS_SOLARIS ${CMAKE_SYSTEM_NAME})
# Windows is easy (for once)
if(WIN32)
set(PLAYER_OS_WIN TRUE BOOL INTERNAL)
endif()
# Check if it's an Apple OS
if(APPLE)
# Check if it's OS X or another MacOS (that's got to be pretty unlikely)
string(REGEX MATCH "Darwin" PLAYER_OS_OSX ${CMAKE_SYSTEM_NAME})
if(NOT PLAYER_OS_OSX)
set(PLAYER_OS_MACOS TRUE BOOL INTERNAL)
endif()
endif()
# QNX
if(QNXNTO)
set(PLAYER_OS_QNX TRUE BOOL INTERNAL)
endif()
if(PLAYER_OS_LINUX)
message(STATUS "Operating system is Linux")
elseif(PLAYER_OS_BSD)
message(STATUS "Operating system is BSD")
elseif(PLAYER_OS_WIN)
message(STATUS "Operating system is Windows")
elseif(PLAYER_OS_OSX)
message(STATUS "Operating system is Apple MacOS X")
elseif(PLAYER_OS_MACOS)
message(STATUS "Operating system is Apple MacOS (not OS X)")
elseif(PLAYER_OS_QNX)
message(STATUS "Operating system is QNX")
elseif(PLAYER_OS_SOLARIS)
message(STATUS "Operating system is Solaris")
else(PLAYER_OS_LINUX)
message(STATUS "Operating system is generic Unix")
endif()
#################################################
# Check for non-case-sensitive filesystems
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/case_sensitive_filesystem
RESULT_VARIABLE FILESYSTEM_CASE_SENSITIVE_RETURN)
if (${FILESYSTEM_CASE_SENSITIVE_RETURN} EQUAL 0)
set(FILESYSTEM_CASE_SENSITIVE TRUE)
else()
set(FILESYSTEM_CASE_SENSITIVE FALSE)
endif()
endmacro()
ign-cmake-ignition-cmake2_2.10.0/cmake/cpack_options.cmake.in 0000664 0001750 0001750 00000002525 14160533245 023743 0 ustar jrivero jrivero set(CPACK_PACKAGE_NAME "@PROJECT_NAME_NO_VERSION@")
set(CPACK_PACKAGE_VENDOR "osrfoundation.org")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"A set of @IGN_DESIGNATION@ classes for robot applications.")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "@PROJECT_NAME_NO_VERSION_LOWER@")
set(CPACK_RESOURCE_FILE_LICENSE "@CMAKE_CURRENT_SOURCE_DIR@/LICENSE")
set(CPACK_RESOURCE_FILE_README "@CMAKE_CURRENT_SOURCE_DIR@/README.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "@CMAKE_CURRENT_SOURCE_DIR@/README.md")
set(CPACK_PACKAGE_MAINTAINER "Nate Koenig ")
set(CPACK_PACKAGE_CONTACT "Nate Koenig ")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "@DPKG_ARCH@")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "@DEBIAN_PACKAGE_DEPENDS@")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION
"A set of @IGN_DESIGNATION@ classes for robot applications.")
set(CPACK_RPM_PACKAGE_ARCHITECTURE "@DPKG_ARCH@")
set(CPACK_RPM_PACKAGE_REQUIRES "@DEBIAN_PACKAGE_DEPENDS@")
set(CPACK_RPM_PACKAGE_DESCRIPTION
"A set of @IGN_DESIGNATION@ classes for robot applications.")
set (CPACK_PACKAGE_FILE_NAME
"@PROJECT_NAME_NO_VERSION_LOWER@-@PROJECT_VERSION_FULL@")
set (CPACK_SOURCE_PACKAGE_FILE_NAME
"@PROJECT_NAME_NO_VERSION_LOWER@-@PROJECT_VERSION_FULL@")
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnImportTarget.cmake 0000664 0001750 0001750 00000016346 14160533245 023567 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#
########################################
# ign_import_target( [INTERFACE]
# [TARGET_NAME ]
# [LIB_VAR ]
# [INCLUDE_VAR ]
# [CFLAGS_VAR ])
#
# This macro will create an imported target based on the variables pertaining
# to , such as _LIBRARIES, _INCLUDE_DIRS, and
# _CFLAGS. Optionally, you can provide TARGET_NAME followed by a
# string, which will then be used as the name of the imported target. If
# TARGET_NAME is not provided, the name of the imported target will default to
# ::.
#
# INTERFACE: Optional. Use INTERFACE when the target does not actually provide
# a library that needs to be linked against (e.g. it is a header-only
# library, or the target is just used to specify compiler flags).
#
# TARGET_NAME: Optional. Explicitly specify the desired imported target name.
# Default is ::.
#
# LIB_VAR: Optional. Explicitly specify the name of the library variable for
# this package. Default is _LIBRARIES.
#
# INCLUDE_VAR: Optional. Explicitly specify the name of the include directory
# variable for this package. Default is _INCLUDE_DIRS.
#
# CFLAGS_VAR: Optional. Explicitly specify the name of the cflags variable for
# this package. Default is _CFLAGS.
#
macro(ign_import_target package)
#------------------------------------
# Define the expected arguments
set(options "INTERFACE")
set(oneValueArgs "TARGET_NAME" "LIB_VAR" "INCLUDE_VAR" "CFLAGS_VAR")
set(multiValueArgs) # We are not using multiValueArgs yet
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_import_target "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#------------------------------------
# Check if a target name has been provided, otherwise use
# ${package}::{$package} as the target name.
if(ign_import_target_TARGET_NAME)
set(target_name ${ign_import_target_TARGET_NAME})
else()
set(target_name ${package}::${package})
endif()
if(NOT TARGET ${target_name})
#------------------------------------
# Use default versions of these build variables if custom versions were not
# provided.
if(NOT ign_import_target_LIB_VAR)
set(ign_import_target_LIB_VAR ${package}_LIBRARIES)
endif()
if(NOT ign_import_target_INCLUDE_VAR)
set(ign_import_target_INCLUDE_VAR ${package}_INCLUDE_DIRS)
endif()
if(NOT ign_import_target_CFLAGS_VAR)
set(ign_import_target_CFLAGS_VAR ${package}_CFLAGS)
endif()
#------------------------------------
# Link against this "imported" target by saying
# target_link_libraries(mytarget package::package), instead of linking
# against the variable package_LIBRARIES with the old-fashioned
# target_link_libraries(mytarget ${package_LIBRARIES}
if(NOT ign_import_target_INTERFACE)
add_library(${target_name} UNKNOWN IMPORTED)
else()
add_library(${target_name} INTERFACE IMPORTED)
endif()
# Do not bother with the IMPORTED_LOCATION or IMPORTED_IMPLIB variables if it
# is an INTERFACE target.
if(NOT ign_import_target_INTERFACE)
if(${ign_import_target_LIB_VAR})
_ign_sort_libraries(${target_name} ${${ign_import_target_LIB_VAR}})
endif()
endif()
if(${ign_import_target_LIB_VAR})
set_target_properties(${target_name} PROPERTIES
INTERFACE_LINK_LIBRARIES "${${ign_import_target_LIB_VAR}}")
endif()
if(${ign_import_target_INCLUDE_VAR})
# TODO: In a later version of cmake, it should be possible to replace this
# with
#
# target_include_directories(${target_name} INTERFACE ${${ign_import_target_INCLUDE_VAR}})
#
# But this will not be possible until we are using whichever version of cmake
# the PR https://gitlab.kitware.com/cmake/cmake/merge_requests/1264
# is available for.
set_property(
TARGET ${target_name}
PROPERTY INTERFACE_INCLUDE_DIRECTORIES
${${ign_import_target_INCLUDE_VAR}})
endif()
if(${ign_import_target_CFLAGS_VAR})
# TODO: See note above. We should eventually be able to replace this with
# target_compile_options(${target_name} INTERFACE ${${ign_import_target_CFLAGS_VAR}})
set_property(
TARGET ${target_name}
PROPERTY INTERFACE_COMPILE_OPTIONS
${${ign_import_target_CFLAGS_VAR}})
endif()
# What about linker flags? Is there no target property for that?
endif()
endmacro()
# This is an awkward hack to give the package both an IMPORTED_LOCATION and
# a set of INTERFACE_LIBRARIES in the event that PkgConfig returns multiple
# libraries for this package. It seems that IMPORTED_LOCATION cannot support
# specifying multiple libraries, so if we have multiple libraries, we need to
# pass them into INTERFACE_LINK_LIBRARIES. However, if IMPORTED_LOCATION is
# missing from the target, the dependencies do not get configured correctly by
# the generator expressions, and the build system will try to link to a nonsense
# garbage file.
#
# TODO: Figure out if there is a better way to fill in the various library
# properties of an imported target.
function(_ign_sort_libraries target_name first_lib)
if(MSVC)
# Note: For MSVC, we only care about the "import library" which is the
# library ending in *.lib. The linker only needs to be told where the
# *.lib library is. The dynamic library (*.dll) only needs to be visible
# to the program at run-time, not at compile or link time. Furthermore,
# find_library on Windows only looks for *.lib files, so we expect that
# results of the form package_LIBRARIES will contain *.lib files when
# running on Windows. IMPORTED_IMPLIB is the target property that
# indicates the "import library" of an "imported target", so that is
# the property that will fill in first and foremost.
#
# TODO: How does MinGW handle libraries?
set_target_properties(${target_name} PROPERTIES
IMPORTED_IMPLIB "${first_lib}")
endif()
set_target_properties(${target_name} PROPERTIES
IMPORTED_LOCATION "${first_lib}")
foreach(extra_lib ${ARGN})
set_target_properties(${target_name} PROPERTIES
INTERFACE_LINK_LIBRARIES "${extra_lib}")
endforeach()
get_target_property(ill ${target_name} INTERFACE_LINK_LIBRARIES)
set_target_properties(${target_name}
PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES ${ill})
set_target_properties(${target_name}
PROPERTIES IMPORTED_LINK_DEPENDENT_LIBRARIES ${ill})
endfunction()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindSQLite3.cmake 0000664 0001750 0001750 00000003247 14160533245 022531 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 SQLite3
#
# Usage of this module is as follows:
#
# find_package(SQLite3 [VERSION [.[.]]])
#
# Variables defined by this module:
#
# SQLite3::SQLite3 Imported target for sqlite3
# SQLite3_FOUND System has sqlite3 library and headers
if(SQLite3_FIND_VERSION)
ign_pkg_check_modules_quiet(SQLite3 "sqlite3 >= ${SQLite3_FIND_VERSION}")
else()
ign_pkg_check_modules_quiet(SQLite3 "sqlite")
endif()
if(MSVC)
set(SQLite3_FOUND TRUE)
find_library(SQLite3_LIBRARIES sqlite3)
if(NOT SQLite3_LIBRARIES)
set(SQLite3_FOUND FALSE)
if(NOT SQLite3_FIND_QUIETLY)
message(STATUS "Looking for sqlite3 library - not found")
endif()
endif()
find_path(SQLite3_INCLUDE_DIRS sqlite3.h)
if(NOT SQLite3_INCLUDE_DIRS)
set(SQLite3_FOUND FALSE)
if(NOT SQLite3_FIND_QUIETLY)
message(STATUS "Looking for sqlite header (sqlite3.h) - not found")
endif()
endif()
ign_import_target(SQLite3)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnConfigureBuild.cmake 0000664 0001750 0001750 00000033745 14160533245 024051 0 ustar jrivero jrivero #.rst
# IgnBuildProject
# -------------------
#
# ign_configure_build()
#
# Configures the build rules of an ignition library project.
#
#===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#################################################
# Configure the build of the ignition project
# Pass the argument HIDE_SYMBOLS_BY_DEFAULT to configure symbol visibility so
# that symbols are hidden unless explicitly marked as visible.
# Pass the argument QUIT_IF_BUILD_ERRORS to have this macro quit cmake when the
# build_errors
macro(ign_configure_build)
#============================================================================
# Parse the arguments that are passed in
set(options HIDE_SYMBOLS_BY_DEFAULT QUIT_IF_BUILD_ERRORS)
set(oneValueArgs)
set(multiValueArgs COMPONENTS)
cmake_parse_arguments(ign_configure_build "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#============================================================================
# Examine the build type. If we do not recognize the type, we will generate
# an error, so this must come before the error handling.
ign_parse_build_type()
#============================================================================
# Ask whether we should make a shared or static library.
option(BUILD_SHARED_LIBS "Set this to true to generate shared libraries (recommended), or false for static libraries" ON)
#============================================================================
# Print warnings and errors
if(build_warnings)
set(all_warnings " CONFIGURATION WARNINGS:")
foreach (msg ${build_warnings})
ign_string_append(all_warnings " -- ${msg}" DELIM "\n")
endforeach ()
message(WARNING "${all_warnings}")
endif (build_warnings)
if(build_errors)
message(SEND_ERROR "-- BUILD ERRORS: These must be resolved before compiling.")
foreach(msg ${build_errors})
message(SEND_ERROR "-- ${msg}")
endforeach()
message(SEND_ERROR "-- END BUILD ERRORS\n")
set(error_str "Errors encountered in build. Please see BUILD ERRORS above.")
if(ign_configure_build_QUIT_IF_BUILD_ERRORS)
message(FATAL_ERROR "${error_str}")
else()
message(WARNING "${error_str}")
endif()
endif()
#============================================================================
# If there are no build errors, try building
if(NOT build_errors)
#--------------------------------------
# Turn on testing
include(CTest)
enable_testing()
#--------------------------------------
# Set up the compiler flags
ign_set_compiler_flags()
#--------------------------------------
# Set up the compiler feature flags to help us choose our standard
ign_set_cxx_feature_flags()
#--------------------------------------
# We want to include both the include directory from the source tree and
# also the include directory that's generated in the build folder,
# ${PROJECT_BINARY_DIR}, so that headers which are generated via cmake will
# be visible to the compiler.
#
# TODO: We should consider removing this include_directories(~) command.
# If these directories are needed by any targets, then we should specify it
# for those targets directly.
if(EXISTS "${PROJECT_SOURCE_DIR}/include")
include_directories("${PROJECT_SOURCE_DIR}/include")
endif()
include_directories("${PROJECT_BINARY_DIR}/include")
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/include")
#--------------------------------------
# Clear the test results directory
#
# TODO: This should probably be in a CI script instead of our build
# configuration script.
execute_process(COMMAND cmake -E remove_directory ${CMAKE_BINARY_DIR}/test_results)
execute_process(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/test_results)
#--------------------------------------
# Create the "all" meta-target
ign_create_all_target()
#--------------------------------------
# Add the source code directories of the core library
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/core")
# If the directory structure has a subdirectory called "core", we will
# use that instead of assuming that src, include, and test subdirectories
# exist in the root directory.
#
# We treat "core" the same way as we treat the component subdirectories.
# It's inserted into the beginning of the list to make sure that the core
# subdirectory is handled before any other.
list(INSERT ign_configure_build_COMPONENTS 0 core)
else()
add_subdirectory(src)
_ign_find_include_script()
endif()
if(BUILD_TESTING AND EXISTS ${CMAKE_CURRENT_LIST_DIR}/test)
add_subdirectory(test)
endif()
#--------------------------------------
# Add the source, include, and test directories to the cppcheck dirs.
# CPPCHECK_DIRS is used in IgnCodeCheck. The variable specifies the
# directories static code analyzers should check. Additional directories
# are added for each component.
set (CPPCHECK_DIRS)
set (potential_cppcheck_dirs
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/test/integration
${CMAKE_SOURCE_DIR}/test/regression
${CMAKE_SOURCE_DIR}/test/performance)
foreach (dir ${potential_cppcheck_dirs})
if (EXISTS ${dir})
list (APPEND CPPCHECK_DIRS ${dir})
endif()
endforeach()
# Includes for cppcheck. This sets include paths for cppcheck. Additional
# directories are added for each component.
set (CPPCHECK_INCLUDE_DIRS)
set (potential_cppcheck_include_dirs
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/include/${PROJECT_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/test/integration
${CMAKE_SOURCE_DIR}/test/regression
${CMAKE_SOURCE_DIR}/test/performance)
foreach (dir ${potential_cppcheck_include_dirs})
if (EXISTS ${dir})
list (APPEND CPPCHECK_INCLUDE_DIRS ${dir})
endif()
endforeach()
#--------------------------------------
# Initialize the list of header directories that should be parsed by doxygen
if(EXISTS "${CMAKE_SOURCE_DIR}/include")
set(ign_doxygen_component_input_dirs "${CMAKE_SOURCE_DIR}/include")
else()
set(ign_doxygen_component_input_dirs "")
endif()
#--------------------------------------
# Add the source code directories of each component if they exist
foreach(component ${ign_configure_build_COMPONENTS})
if(NOT SKIP_${component} AND NOT INTERNAL_SKIP_${component})
set(found_${component}_src FALSE)
# Append the component's include directory to both CPPCHECK_DIRS and
# CPPCHECK_INCLUDE_DIRS
list(APPEND CPPCHECK_DIRS ${CMAKE_CURRENT_LIST_DIR}/${component}/include)
list(APPEND CPPCHECK_INCLUDE_DIRS
${CMAKE_CURRENT_LIST_DIR}/${component}/include)
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${component}/include")
# Note: It seems we need to give the delimiter exactly this many
# backslashes in order to get a \ plus a newline. This might be
# dependent on the implementation of ign_string_append, so be careful
# when changing the implementation of that function.
ign_string_append(ign_doxygen_component_input_dirs
"${CMAKE_CURRENT_LIST_DIR}/${component}/include"
DELIM " \\\\\\\\\n ")
endif()
# Append the component's source directory to CPPCHECK_DIRS.
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${component}/src")
list(APPEND CPPCHECK_DIRS ${CMAKE_CURRENT_LIST_DIR}/${component}/src)
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${component}/CMakeLists.txt")
# If the component's directory has a top-level CMakeLists.txt, use
# that.
add_subdirectory(${component})
set(found_${component}_src TRUE)
else()
# If the component's directory does not have a top-level
# CMakeLists.txt, try to call the expected set of subdirectories
# individually. This saves us from needing to create very redundant
# CMakeLists.txt files that do nothing but redirect us to these
# subdirectories.
# Add the source files
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${component}/src/CMakeLists.txt")
add_subdirectory(${component}/src)
set(found_${component}_src TRUE)
endif()
_ign_find_include_script(COMPONENT ${component})
# Add the tests
if(BUILD_TESTING AND
EXISTS "${CMAKE_CURRENT_LIST_DIR}/${component}/test/CMakeLists.txt")
add_subdirectory(${component}/test)
endif()
endif()
if(NOT found_${component}_src)
message(AUTHOR_WARNING
"Could not find a top-level CMakeLists.txt or src/CMakeLists.txt "
"for the component [${component}]!")
endif()
else()
set(skip_msg "Skipping the component [${component}]")
if(SKIP_${component})
ign_string_append(skip_msg "by user request")
elseif(${component}_MISSING_DEPS)
ign_string_append(skip_msg "because the following packages are missing: ${${component}_MISSING_DEPS}")
endif()
message(STATUS "${skip_msg}")
endif()
endforeach()
#--------------------------------------
# Export the "all" meta-target
ign_export_target_all()
#--------------------------------------
# Create codecheck target
include(IgnCodeCheck)
ign_setup_target_for_codecheck()
#--------------------------------------
# If we made it this far, the configuration was successful
message(STATUS "Build configuration successful")
endif()
endmacro()
macro(ign_set_cxx_feature_flags)
set(IGN_KNOWN_CXX_STANDARDS 11 14 17)
set(IGN_CXX_11_FEATURES cxx_std_11)
set(IGN_CXX_14_FEATURES cxx_std_14)
set(IGN_CXX_17_FEATURES cxx_std_17)
endmacro()
function(_ign_find_include_script)
#------------------------------------
# Define the expected arguments
set(options) # Unused
set(oneValueArgs COMPONENT)
set(multiValueArgs) # Unused
#------------------------------------
# Parse the arguments
cmake_parse_arguments(_ign_find_include_script "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#------------------------------------
# Set the starting point
set(include_start "${CMAKE_CURRENT_LIST_DIR}")
if(_ign_find_include_script_COMPONENT)
ign_string_append(include_start ${_ign_find_include_script_COMPONENT} DELIM "/")
endif()
# Check each level of depth to find the first CMakeLists.txt. This allows us
# to have custom behavior for each include directory structure while also
# allowing us to just have one leaf CMakeLists.txt file if a project doesn't
# need any custom configuration in its include directories.
if(EXISTS "${include_start}/include")
if(EXISTS "${include_start}/include/CMakeLists.txt")
add_subdirectory("${include_start}/include")
elseif(EXISTS "${include_start}/include/ignition/CMakeLists.txt")
add_subdirectory("${include_start}/include/ignition")
elseif(EXISTS "${include_start}/include/${PROJECT_INCLUDE_DIR}/CMakeLists.txt")
add_subdirectory("${include_start}/include/${PROJECT_INCLUDE_DIR}")
else()
message(AUTHOR_WARNING
"You have an include directory [${include_start}/include] without a "
"CMakeLists.txt. This means its headers will not get installed!")
endif()
endif()
endfunction()
macro(ign_parse_build_type)
#============================================================================
# If a build type is not specified, set it to RelWithDebInfo by default
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif()
# Handle NONE in MSVC as blank and default to RelWithDebInfo
if (MSVC AND CMAKE_BUILD_TYPE_UPPERCASE STREQUAL "NONE")
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif()
# Convert to uppercase in order to support arbitrary capitalization
string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_UPPERCASE)
#============================================================================
# Set variables based on the build type
set(BUILD_TYPE_PROFILE FALSE)
set(BUILD_TYPE_RELEASE FALSE)
set(BUILD_TYPE_RELWITHDEBINFO FALSE)
set(BUILD_TYPE_MINSIZEREL FALSE)
set(BUILD_TYPE_NONE FALSE)
set(BUILD_TYPE_DEBUG FALSE)
if("${CMAKE_BUILD_TYPE_UPPERCASE}" STREQUAL "DEBUG")
set(BUILD_TYPE_DEBUG TRUE)
elseif("${CMAKE_BUILD_TYPE_UPPERCASE}" STREQUAL "RELEASE")
set(BUILD_TYPE_RELEASE TRUE)
elseif("${CMAKE_BUILD_TYPE_UPPERCASE}" STREQUAL "RELWITHDEBINFO")
set(BUILD_TYPE_RELWITHDEBINFO TRUE)
elseif("${CMAKE_BUILD_TYPE_UPPERCASE}" STREQUAL "MINSIZEREL")
set(BUILD_TYPE_MINSIZEREL TRUE)
elseif("${CMAKE_BUILD_TYPE_UPPERCASE}" STREQUAL "NONE")
set(BUILD_TYPE_NONE TRUE)
elseif("${CMAKE_BUILD_TYPE_UPPERCASE}" STREQUAL "COVERAGE")
include(IgnCodeCoverage)
set(BUILD_TYPE_DEBUG TRUE)
ign_setup_target_for_coverage(
OUTPUT_NAME coverage
TARGET_NAME coverage
TEST_RUNNER ctest)
ign_setup_target_for_coverage(
BRANCH_COVERAGE
OUTPUT_NAME coverage-branch
TARGET_NAME coverage-branch
TEST_RUNNER ctest)
elseif("${CMAKE_BUILD_TYPE_UPPERCASE}" STREQUAL "PROFILE")
set(BUILD_TYPE_PROFILE TRUE)
else()
ign_build_error("CMAKE_BUILD_TYPE [${CMAKE_BUILD_TYPE}] unknown. Valid options are: Debug Release RelWithDebInfo MinSizeRel Profile Check")
endif()
endmacro()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnPython.cmake 0000664 0001750 0001750 00000001663 14160533245 022423 0 ustar jrivero jrivero # Copyright 2020 Open Source Robotics Foundation, Inc.
#
# Licensed 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.
# Copied from ament/ament_cmake: ament_cmake/ament_cmake_core/cmake/core/python.cmake
set(PYTHON_VERSION "" CACHE STRING
"Specify specific Python version to use ('major.minor' or 'major')")
# if not specified otherwise use Python 3
if(NOT PYTHON_VERSION)
set(PYTHON_VERSION "3")
endif()
find_package(PythonInterp ${PYTHON_VERSION} QUIET)
ign-cmake-ignition-cmake2_2.10.0/cmake/ign_auto_headers.hh.in 0000664 0001750 0001750 00000001550 14160533245 023723 0 ustar jrivero jrivero /*
* Copyright (C) 2017 Open Source Robotics Foundation
*
* Licensed 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.
*
*/
// ****** Do not modify this file. ******
// This file is automatically generated by CMake. Changes should instead be
// made to cmake/ign_auto_headers.hh.in in ignition-cmake
#include <@PROJECT_INCLUDE_DIR@/config.hh>
${ign_headers}
ign-cmake-ignition-cmake2_2.10.0/cmake/FindZIP.cmake 0000664 0001750 0001750 00000003520 14160533245 021741 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 zip.
#
# Usage of this module as follows:
#
# find_package(ZIP)
#
# Variables defined by this module:
#
# ZIP_FOUND System has ZIP libs/headers
# ZIP_INCLUDE_DIRS The location of ZIP headers
# ZIP_LIBRARIES The ZIP libraries
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(ZIP libzip)
# If that failed, then fall back to manual detection.
if(NOT ZIP_FOUND)
if(NOT ZIP_FIND_QUIETLY)
message(STATUS "Attempting manual search for zip")
endif()
find_path(ZIP_INCLUDE_DIRS zip.h ${ZIP_INCLUDE_DIRS} ENV CPATH)
find_library(ZIP_LIBRARIES NAMES zip)
set(ZIP_FOUND true)
if(NOT ZIP_INCLUDE_DIRS)
if(NOT ZIP_FIND_QUIETLY)
message(STATUS "Looking for zip headers - not found")
endif()
set(ZIP_FOUND false)
endif()
if(NOT ZIP_LIBRARIES)
if(NOT ZIP_FIND_QUIETLY)
message (STATUS "Looking for zip library - not found")
endif()
set(ZIP_FOUND false)
endif()
if(ZIP_FOUND)
include(IgnImportTarget)
ign_import_target(ZIP)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
ZIP
REQUIRED_VARS ZIP_FOUND) ign-cmake-ignition-cmake2_2.10.0/cmake/IgnPackaging.cmake 0000664 0001750 0001750 00000034201 14160533245 023020 0 ustar jrivero jrivero #.rst
# IgnPackaging
# ----------------
#
# ign_setup_packages
#
# Sets up package information for an ignition library project.
#
# ign_create_package
#
# Creates a package for an ignition library project
#
#===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#################################################
# Set up package information
macro(ign_setup_packages)
#============================================================================
# Use GNUInstallDirs to get canonical paths.
# We use this filesystem style on Windows as well, because (quite frankly)
# Windows does not seem to have any sensible convention of its own for
# installing development libraries. (If anyone is aware of a widely accepted
# convention for where to install development libraries on Windows, please
# correct this.)
include(GNUInstallDirs)
#============================================================================
#Find available package generators
# DEB
if("${CMAKE_SYSTEM}" MATCHES "Linux")
find_program(DPKG_PROGRAM dpkg)
if(EXISTS ${DPKG_PROGRAM})
list(APPEND CPACK_GENERATOR "DEB")
endif(EXISTS ${DPKG_PROGRAM})
find_program(RPMBUILD_PROGRAM rpmbuild)
endif()
list(APPEND CPACK_SOURCE_GENERATOR "TBZ2")
list(APPEND CPACK_SOURCE_GENERATOR "ZIP")
list(APPEND CPACK_SOURCE_IGNORE_FILES "TODO;\.hg/;\.sw.$;/build/;\.hgtags;\.hgignore;appveyor\.yml;\.travis\.yml;codecov\.yml")
include(InstallRequiredSystemLibraries)
#execute_process(COMMAND dpkg --print-architecture _NPROCE)
set(DEBIAN_PACKAGE_DEPENDS "")
set(RPM_PACKAGE_DEPENDS "")
set(PROJECT_CPACK_CFG_FILE "${PROJECT_BINARY_DIR}/cpack_options.cmake")
#============================================================================
# Set CPack variables
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION_FULL}")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
if(CPACK_GENERATOR)
message(STATUS "Found CPack generators: ${CPACK_GENERATOR}")
configure_file("${IGNITION_CMAKE_DIR}/cpack_options.cmake.in"
${PROJECT_CPACK_CFG_FILE} @ONLY)
set(CPACK_PROJECT_CONFIG_FILE ${PROJECT_CPACK_CFG_FILE})
include(CPack)
endif()
#============================================================================
# If we're configuring only to package source, stop here
if(PACKAGE_SOURCE_ONLY)
message(WARNING "Configuration was done in PACKAGE_SOURCE_ONLY mode."
"You can build a tarball (make package_source), but nothing else.")
return()
endif()
#============================================================================
# Developer's option to cache PKG_CONFIG_PATH and
# LD_LIBRARY_PATH for local installs
if(PKG_CONFIG_PATH)
set(ENV{PKG_CONFIG_PATH} ${PKG_CONFIG_PATH}:$ENV{PKG_CONFIG_PATH})
endif()
if(LD_LIBRARY_PATH)
set(ENV{LD_LIBRARY_PATH} ${LD_LIBRARY_PATH}:$ENV{LD_LIBRARY_PATH})
endif()
#============================================================================
# Set up installation directories
set(IGN_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}")
set(IGN_INCLUDE_INSTALL_DIR_POSTFIX "ignition/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}")
set(IGN_INCLUDE_INSTALL_DIR_FULL "${IGN_INCLUDE_INSTALL_DIR}/${IGN_INCLUDE_INSTALL_DIR_POSTFIX}")
set(IGN_DATA_INSTALL_DIR_POSTFIX "ignition/${PROJECT_NAME_LOWER}")
set(IGN_DATA_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/${IGN_DATA_INSTALL_DIR_POSTFIX}")
set(IGN_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
set(IGN_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR})
#============================================================================
# Handle the user's RPATH setting
option(USE_FULL_RPATH "Turn on to enable the full RPATH" OFF)
if(USE_FULL_RPATH)
# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${IGN_LIB_INSTALL_DIR}")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# the RPATH to be used when installing, but only if its not a system directory
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${IGN_LIB_INSTALL_DIR}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${IGN_LIB_INSTALL_DIR}")
endif("${isSystemDir}" STREQUAL "-1")
endif()
#============================================================================
# Add uninstall target
configure_file(
"${IGNITION_CMAKE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
"${CMAKE_COMMAND}" -P
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
endmacro()
macro(ign_create_packages)
#============================================================================
# Load platform-specific build hooks if present.
ign_load_build_hooks()
#============================================================================
# Tell the user what their settings are
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
endmacro()
#################################################
# _ign_create_pkgconfig([COMPONENT ])
#
# Provide the name of the target for which we will generate package config info.
# If the target is a component, pass in the COMPONENT argument followed by the
# component's name.
#
# NOTE: This will be called automatically by ign_create_core_library(~) and
# ign_add_component(~), so users of ignition-cmake should not call this
# function.
#
# NOTE: For ignition-cmake developers, the variables needed by ignition.pc.in or
# ignition-component.pc.in MUST be set before calling this function.
#
# Create a pkgconfig file for your target, and install it.
function(_ign_create_pkgconfig)
#------------------------------------
# Define the expected arguments
set(options)
set(oneValueArgs COMPONENT) # Unused
set(multiValueArgs) # Unused
#------------------------------------
# Parse the arguments
cmake_parse_arguments(_ign_create_pkgconfig "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#------------------------------------
# Choose which input file to use
if(_ign_create_pkgconfig_COMPONENT)
set(pkgconfig_input "${IGNITION_CMAKE_DIR}/pkgconfig/ignition-component.pc.in")
set(target_name ${PROJECT_LIBRARY_TARGET_NAME}-${_ign_create_pkgconfig_COMPONENT})
else()
set(pkgconfig_input "${IGNITION_CMAKE_DIR}/pkgconfig/ignition.pc.in")
set(target_name ${PROJECT_LIBRARY_TARGET_NAME})
endif()
set(pkgconfig_output "${CMAKE_BINARY_DIR}/cmake/pkgconfig/${target_name}.pc")
set(pkgconfig_install_dir "${IGN_LIB_INSTALL_DIR}/pkgconfig")
file(RELATIVE_PATH
PC_CONFIG_RELATIVE_PATH_TO_PREFIX
"${CMAKE_INSTALL_PREFIX}/${pkgconfig_install_dir}"
"${CMAKE_INSTALL_PREFIX}"
)
configure_file(${pkgconfig_input} ${pkgconfig_output} @ONLY)
install(
FILES ${pkgconfig_output}
DESTINATION ${pkgconfig_install_dir}
COMPONENT pkgconfig)
endfunction()
#################################################
# _ign_create_cmake_package([COMPONENT ]
# [LEGACY_PROJECT_PREFIX ])
#
# Provide the name of the target that will be installed and exported. If the
# target is a component, pass in the COMPONENT argument followed by the
# component's name.
#
# For packages like sdformat that use inconsistent case in the legacy cmake
# variable names (like SDFormat_LIBRARIES), the LEGACY_PROJECT_PREFIX argument
# can be used to specify the prefix of these variables.
#
# NOTE: This will be called automatically by ign_create_core_library(~) and
# ign_add_component(~), so users of ignition-cmake should not call this
# function.
#
# NOTE: For ignition-cmake developers, some of the variables needed by
# ignition-config.cmake.in or ignition-component-config.cmake.in MUST be
# set before calling this function. The following variables are set
# automatically by this function:
# - import_target_name
# - target_output_filename
#
# Make the cmake config files for this target
function(_ign_create_cmake_package)
#------------------------------------
# Define the expected arguments
set(options ALL)
set(oneValueArgs COMPONENT LEGACY_PROJECT_PREFIX)
set(multiValueArgs) # Unused
#------------------------------------
# Parse the arguments
cmake_parse_arguments(_ign_create_cmake_package "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(_ign_create_cmake_package_COMPONENT AND _ign_create_cmake_package_ALL)
message(FATAL_ERROR
"_ign_create_cmake_package was called with both ALL and COMPONENT "
"specified. This is not allowed!")
endif()
#------------------------------------
# Set configuration arguments
if(_ign_create_cmake_package_COMPONENT)
set(component ${_ign_create_cmake_package_COMPONENT})
set(target_name ${PROJECT_LIBRARY_TARGET_NAME}-${component})
set(ign_config_input "${IGNITION_CMAKE_DIR}/ignition-component-config.cmake.in")
set(simple_import_name ${component})
elseif(_ign_create_cmake_package_ALL)
set(ign_config_input "${IGNITION_CMAKE_DIR}/ignition-all-config.cmake.in")
set(target_name ${PROJECT_LIBRARY_TARGET_NAME}-all)
set(all_pkg_name ${PROJECT_LIBRARY_TARGET_NAME}-all)
set(simple_import_name all)
else()
set(target_name ${PROJECT_LIBRARY_TARGET_NAME})
set(ign_config_input "${IGNITION_CMAKE_DIR}/ignition-config.cmake.in")
set(simple_import_name core)
endif()
if(_ign_create_cmake_package_LEGACY_PROJECT_PREFIX)
set(LEGACY_PROJECT_PREFIX ${_ign_create_cmake_package_LEGACY_PROJECT_PREFIX})
else()
set(LEGACY_PROJECT_PREFIX ${PROJECT_NAME_NO_VERSION_UPPER})
endif()
# This gets used by the ignition-*.config.cmake.in files
set(target_output_filename ${target_name}-targets.cmake)
set(ign_config_output "${PROJECT_BINARY_DIR}/cmake/${target_name}-config.cmake")
set(ign_version_output "${PROJECT_BINARY_DIR}/cmake/${target_name}-config-version.cmake")
set(ign_target_ouput "${PROJECT_BINARY_DIR}/cmake/${target_output_filename}")
# NOTE: Each component needs to go into its own cmake directory in order to be
# found by cmake's native find_package(~) command.
set(ign_config_install_dir "${IGN_LIB_INSTALL_DIR}/cmake/${target_name}")
set(ign_namespace ${PROJECT_LIBRARY_TARGET_NAME}::)
set(import_target_name ${ign_namespace}${target_name})
set(simple_import_name ${ign_namespace}${simple_import_name})
# Configure the package config file. It will be installed to
# "[lib]/cmake/ignition-/" where [lib] is the library
# installation directory.
configure_package_config_file(
${ign_config_input}
${ign_config_output}
INSTALL_DESTINATION ${ign_config_install_dir}
PATH_VARS IGN_LIB_INSTALL_DIR IGN_INCLUDE_INSTALL_DIR_FULL)
# Use write_basic_package_version_file to generate a ConfigVersion file that
# allow users of the library to specify the API or version to depend on
write_basic_package_version_file(
${ign_version_output}
VERSION "${PROJECT_VERSION_FULL_NO_SUFFIX}"
COMPATIBILITY SameMajorVersion)
# Install the configuration files to the configuration installation directory
install(
FILES
${ign_config_output}
${ign_version_output}
DESTINATION ${ign_config_install_dir}
COMPONENT cmake)
# Create *-targets.cmake file for build directory
export(
EXPORT ${target_name}
FILE ${ign_target_ouput}
# We add a namespace that ends with a :: to the name of the exported target.
# This is so consumers of the project can call
# find_package(ignition-)
# target_link_libraries(consumer_project ignition-::ignition-)
# and cmake will understand that the consumer is asking to link the imported
# target "ignition-" to their "consumer_project" rather than asking
# to link a library named "ignition-". In other words, when
# target_link_libraries is given a name that contains double-colons (::) it
# will never mistake it for a library name, and it will throw an error if
# it cannot find a target with the given name.
#
# The advantage of linking against a target rather than a library is that
# you will automatically link against all the dependencies of that target.
# This also helps us create find-config files that are relocatable.
NAMESPACE ${ign_namespace})
# Install *-targets.cmake file
install(
EXPORT ${target_name}
DESTINATION ${ign_config_install_dir}
FILE ${target_output_filename}
# See explanation above for NAMESPACE
NAMESPACE ${ign_namespace})
endfunction()
#################################################
# Make the cmake config files for this project
# Pass an argument to specify the directory where the CMakeLists.txt for the
# build hooks is located. If no argument is provided, we default to:
# ${PROJECT_SOURCE_DIR}/packager-hooks
function(ign_load_build_hooks)
if(ARGV0)
set(hook_dir ${ARGV0})
else()
set(hook_dir "${PROJECT_SOURCE_DIR}/cmake/packager-hooks")
endif()
if(EXISTS ${hook_dir}/CMakeLists.txt)
message(STATUS "Loading packager build hooks from ${hook_dir}")
add_subdirectory(${hook_dir})
endif()
endfunction()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindAVCODEC.cmake 0000664 0001750 0001750 00000002127 14160533245 022345 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 avcodec
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(AVCODEC libavcodec)
if(NOT AVCODEC_FOUND)
include(IgnManualSearch)
ign_manual_search(AVCODEC
HEADER_NAMES "libavcodec/avcodec.h"
LIBRARY_NAMES "avcodec")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
AVCODEC
REQUIRED_VARS AVCODEC_FOUND)
ign-cmake-ignition-cmake2_2.10.0/cmake/FindIgnOGRE2.cmake 0000664 0001750 0001750 00000036545 14160533245 022570 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 OGRE2 headers and libraries
#
# Usage of this module as follows:
#
# ign_find_package(IgnOGRE2)
#
# Variables defined by this module:
#
# OGRE2_FOUND System has OGRE libs/headers
# OGRE2_LIBRARIES The OGRE libraries
# OGRE2_INCLUDE_DIRS The location of OGRE headers
# OGRE2_VERSION Full OGRE version in the form of MAJOR.MINOR.PATCH
# OGRE2_VERSION_MAJOR OGRE major version
# OGRE2_VERSION_MINOR OGRE minor version
# OGRE2_VERSION_PATCH OGRE patch version
# OGRE2_RESOURCE_PATH Path to ogre plugins directory
# IgnOGRE2::IgnOGRE2 Imported target for OGRE2
#
# On Windows, we assume that all the OGRE* defines are passed in manually
# to CMake.
#
# Supports finding the following OGRE2 components: HlmsPbs, HlmsUnlit, Overlay
#
# Example usage:
#
# ign_find_package(IgnOGRE2
# VERSION 2.2.0
# COMPONENTS HlmsPbs HlmsUnlit Overlay)
# sanity check
if (${IgnOGRE2_FIND_VERSION_MAJOR})
if (${IgnOGRE2_FIND_VERSION_MAJOR} VERSION_LESS "2")
set (OGRE2_FOUND false)
return()
endif()
endif()
message(STATUS "-- Finding OGRE 2.${IgnOGRE2_FIND_VERSION_MINOR}")
set(OGRE2_INSTALL_PATH "OGRE-2.${IgnOGRE2_FIND_VERSION_MINOR}")
macro(append_library VAR LIB)
if(EXISTS "${LIB}")
list(APPEND ${VAR} ${LIB})
endif()
endmacro()
# filter all ocurrences of LIBRARY_STR with the form of: debug;;optimized;
# based on CMAKE_BUILD_TYPE
macro(select_lib_by_build_type LIBRARY_STR OUTPUT_VAR)
foreach(library ${LIBRARY_STR})
if(library STREQUAL optimized)
set(conf optimized)
elseif(library STREQUAL debug)
set(conf debug)
else()
if(conf STREQUAL optimized)
append_library(LIB_RELEASE ${library})
set(conf)
elseif(conf STREQUAL debug)
append_library(LIB_DEBUG ${library})
set(conf)
else()
# assume library without debug/optimized prefix
append_library(LIB_RELEASE ${library})
append_library(LIB_DEBUG ${library})
endif()
endif()
endforeach()
if(LIB_DEBUG AND CMAKE_BUILD_TYPE STREQUAL "Debug")
set(${OUTPUT_VAR} "${LIB_DEBUG}")
elseif(LIB_RELEASE)
set(${OUTPUT_VAR} "${LIB_RELEASE}")
endif()
endmacro()
# this macro and the version parsing logic below is taken from the
# FindOGRE.cmake file distributed by ogre
macro(get_preprocessor_entry CONTENTS KEYWORD VARIABLE)
string(REGEX MATCH
"# *define +${KEYWORD} +((\"([^\n]*)\")|([^ \n]*))"
PREPROC_TEMP_VAR
${${CONTENTS}}
)
if (CMAKE_MATCH_3)
set(${VARIABLE} ${CMAKE_MATCH_3})
else ()
set(${VARIABLE} ${CMAKE_MATCH_4})
endif ()
endmacro()
if (NOT WIN32)
set(PKG_CONFIG_PATH_ORIGINAL $ENV{PKG_CONFIG_PATH})
# Note: OGRE2 installed from debs is named OGRE-2.2 while the version
# installed from source does not have the 2.2 suffix
# look for OGRE2 installed from debs
ign_pkg_check_modules_quiet(OGRE2 ${OGRE2_INSTALL_PATH} NO_CMAKE_ENVIRONMENT_PATH QUIET)
if (OGRE2_FOUND)
set(IGN_PKG_NAME ${OGRE2_INSTALL_PATH})
else()
# look for OGRE2 installed from source
set(PKG_CONFIG_PATH_TMP ${PKG_CONFIG_PATH_ORIGINAL})
execute_process(COMMAND pkg-config --variable pc_path pkg-config
OUTPUT_VARIABLE _pkgconfig_invoke_result
RESULT_VARIABLE _pkgconfig_failed)
if(_pkgconfig_failed)
IGN_BUILD_WARNING ("Failed to get pkg-config search paths")
elseif (NOT _pkgconfig_invoke_result STREQUAL "")
set (PKG_CONFIG_PATH_TMP "${PKG_CONFIG_PATH_TMP}:${_pkgconfig_invoke_result}")
endif()
# check and see if there are any paths at all
if ("${PKG_CONFIG_PATH_TMP}" STREQUAL "")
message("No valid pkg-config search paths found")
return()
endif()
string(REPLACE ":" ";" PKG_CONFIG_PATH_TMP ${PKG_CONFIG_PATH_TMP})
# loop through pkg config paths and find an ogre version that is >= 2.0.0
foreach(pkg_path ${PKG_CONFIG_PATH_TMP})
set(ENV{PKG_CONFIG_PATH} ${pkg_path})
pkg_check_modules(OGRE2 "OGRE" NO_CMAKE_ENVIRONMENT_PATH QUIET)
if (OGRE2_FOUND)
if (${OGRE2_VERSION} VERSION_LESS 2.0.0)
set (OGRE2_FOUND false)
else ()
# pkg_check_modules does not provide complete path to libraries
# So update variable to point to full path
set(OGRE2_LIBRARY_NAME ${OGRE2_LIBRARIES})
find_library(OGRE2_LIBRARY NAMES ${OGRE2_LIBRARY_NAME}
HINTS ${OGRE2_LIBRARY_DIRS} NO_DEFAULT_PATH)
if ("${OGRE2_LIBRARY}" STREQUAL "OGRE2_LIBRARY-NOTFOUND")
set(OGRE2_FOUND false)
continue()
else()
set(OGRE2_LIBRARIES ${OGRE2_LIBRARY})
endif()
set(IGN_PKG_NAME "OGRE")
break()
endif()
endif()
endforeach()
endif()
if (NOT OGRE2_FOUND)
return()
endif()
# use pkg-config to find ogre plugin path
# do it here before resetting the pkg-config paths
execute_process(COMMAND pkg-config --variable=plugindir ${IGN_PKG_NAME}
OUTPUT_VARIABLE _pkgconfig_invoke_result
RESULT_VARIABLE _pkgconfig_failed)
if(_pkgconfig_failed)
IGN_BUILD_WARNING ("Failed to find OGRE's plugin directory. The build will succeed, but there will likely be run-time errors.")
else()
set(OGRE2_PLUGINDIR ${_pkgconfig_invoke_result})
endif()
# reset pkg config path
set(ENV{PKG_CONFIG_PATH} ${PKG_CONFIG_PATH_ORIGINAL})
# verify ogre header can be found in the include path
find_path(OGRE2_INCLUDE
NAMES Ogre.h
PATHS ${OGRE2_INCLUDE_DIRS}
NO_DEFAULT_PATH
)
if(NOT OGRE2_INCLUDE)
set(OGRE2_FOUND false)
return()
endif()
# manually search and append the the RenderSystem/GL3Plus path to
# OGRE2_INCLUDE_DIRS so OGRE GL headers can be found
foreach (dir ${OGRE2_INCLUDE_DIRS})
get_filename_component(dir_name "${dir}" NAME)
if ("${dir_name}" STREQUAL ${IGN_PKG_NAME})
set(dir_include "${dir}/RenderSystems/GL3Plus")
else()
set(dir_include "${dir}")
endif()
list(APPEND OGRE2_INCLUDE_DIRS ${dir_include})
endforeach()
file(READ ${OGRE2_INCLUDE}/OgrePrerequisites.h OGRE_TEMP_VERSION_CONTENT)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MAJOR OGRE2_VERSION_MAJOR)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MINOR OGRE2_VERSION_MINOR)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_PATCH OGRE2_VERSION_PATCH)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_NAME OGRE2_VERSION_NAME)
set(OGRE2_VERSION "${OGRE2_VERSION_MAJOR}.${OGRE2_VERSION_MINOR}.${OGRE2_VERSION_PATCH}")
# find ogre components
include(IgnImportTarget)
foreach(component ${IgnOGRE2_FIND_COMPONENTS})
find_library(OGRE2-${component}
NAMES
"Ogre${component}_d.${OGRE2_VERSION}"
"Ogre${component}_d"
"Ogre${component}.${OGRE2_VERSION}"
"Ogre${component}"
HINTS ${OGRE2_LIBRARY_DIRS})
if (NOT "OGRE2-${component}" STREQUAL "OGRE2-${component}-NOTFOUND")
# create a new target for each component
set(component_TARGET_NAME "IgnOGRE2-${component}::IgnOGRE2-${component}")
set(component_INCLUDE_DIRS ${OGRE2_INCLUDE_DIRS})
# append the Hlms/Common include dir if it exists.
string(FIND ${component} "Hlms" HLMS_POS)
if(${HLMS_POS} GREATER -1)
foreach (dir ${OGRE2_INCLUDE_DIRS})
get_filename_component(dir_name "${dir}" NAME)
if ("${dir_name}" STREQUAL ${IGN_PKG_NAME})
set(dir_include "${dir}/Hlms/Common")
if (EXISTS ${dir_include})
list(APPEND component_INCLUDE_DIRS ${dir_include})
endif()
endif()
endforeach()
endif()
set(component_LIBRARY_DIRS ${OGRE2_LIBRARY_DIRS})
set(component_LIBRARIES ${OGRE2-${component}})
ign_import_target(${component} TARGET_NAME ${component_TARGET_NAME}
LIB_VAR component_LIBRARIES
INCLUDE_VAR component_INCLUDE_DIRS)
# add it to the list of ogre libraries
list(APPEND OGRE2_LIBRARIES ${component_TARGET_NAME})
elseif(IgnOGRE2_FIND_REQUIRED_${component})
set(OGRE2_FOUND false)
endif()
endforeach()
if ("${OGRE2_PLUGINDIR}" STREQUAL "")
# set path to find ogre plugins
# keep variable naming consistent with ogre 1
# TODO currently using harded paths based on dir structure in ubuntu
foreach(resource_path ${OGRE2_LIBRARY_DIRS})
list(APPEND OGRE2_RESOURCE_PATH "${resource_path}/OGRE")
endforeach()
else()
set(OGRE2_RESOURCE_PATH ${OGRE2_PLUGINDIR})
# Seems that OGRE2_PLUGINDIR can end in a newline, which will cause problems
# when we pass it to the compiler later.
string(REPLACE "\n" "" OGRE2_RESOURCE_PATH ${OGRE2_RESOURCE_PATH})
endif()
# We need to manually specify the pkgconfig entry (and type of entry),
# because ign_pkg_check_modules does not work for it.
include(IgnPkgConfig)
ign_pkg_config_library_entry(IgnOGRE2 OgreMain)
else() #WIN32
set(OGRE2_FOUND TRUE)
set(OGRE_LIBRARIES "")
set(OGRE2_VERSION "")
set(OGRE2_VERSION_MAJOR "")
set(OGRE2_VERSION_MINOR "")
set(OGRE2_RESOURCE_PATH "")
set(OGRE2_SEARCH_VER "OGRE-${IgnOGRE2_FIND_VERSION_MAJOR}.${IgnOGRE2_FIND_VERSION_MINOR}")
set(OGRE2_PATHS "")
set(OGRE2_INC_PATHS "")
foreach(_rootPath ${VCPKG_CMAKE_FIND_ROOT_PATH})
list(APPEND OGRE2_PATHS "${_rootPath}/lib/${OGRE2_SEARCH_VER}/")
list(APPEND OGRE2_PATHS "${_rootPath}/lib/${OGRE2_SEARCH_VER}/manual-link/")
list(APPEND OGRE2_INC_PATHS "${_rootPath}/include/${OGRE2_SEARCH_VER}")
endforeach()
find_library(OGRE2_LIBRARY
NAMES "OgreMain"
HINTS ${OGRE2_PATHS}
NO_DEFAULT_PATH)
find_path(OGRE2_INCLUDE
NAMES "Ogre.h"
HINTS ${OGRE2_INC_PATHS})
if("${OGRE2_LIBRARY}" STREQUAL "OGRE2_LIBRARY-NOTFOUND")
set(OGRE2_FOUND false)
else()
set(OGRE2_LIBRARIES ${OGRE2_LIBRARY})
endif()
if(NOT OGRE2_INCLUDE)
set(OGRE2_FOUND false)
endif()
if (OGRE2_FOUND)
set(OGRE2_INCLUDE_DIRS ${OGRE2_INCLUDE})
set(OGRE2_LIBRARY_DIRS ${OGRE2_PATHS})
file(READ ${OGRE2_INCLUDE}/OgrePrerequisites.h OGRE_TEMP_VERSION_CONTENT)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MAJOR OGRE2_VERSION_MAJOR)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MINOR OGRE2_VERSION_MINOR)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_PATCH OGRE2_VERSION_PATCH)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_NAME OGRE2_VERSION_NAME)
set(OGRE2_VERSION "${OGRE2_VERSION_MAJOR}.${OGRE2_VERSION_MINOR}.${OGRE2_VERSION_PATCH}")
set(OGRE_TEMP_VERSION_CONTENT "")
macro(ogre_find_component COMPONENT HEADER PATH_HINTS)
set(PREFIX OGRE2_${COMPONENT})
find_path(${PREFIX}_INCLUDE_DIR
NAMES ${HEADER}
HINTS ${OGRE2_INCLUDE_DIRS}
PATH_SUFFIXES
${PATH_HINTS} ${COMPONENT} ${OGRE2_SEARCH_VER}/${COMPONENT})
find_library(${PREFIX}_LIBRARY
NAMES
"Ogre${COMPONENT}"
"Ogre${COMPONENT}_d"
HINTS
${OGRE2_LIBRARY_DIRS}
NO_DEFAULT_PATH)
if (NOT ${PREFIX}_FOUND)
if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY)
set(${PREFIX}_FOUND TRUE)
set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR})
set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY})
message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}")
endif()
endif()
endmacro()
macro(ogre_find_plugin PLUGIN HEADER)
set(PREFIX OGRE2_${PLUGIN})
string(REPLACE "RenderSystem_" "" PLUGIN_TEMP ${PLUGIN})
string(REPLACE "Plugin_" "" PLUGIN_NAME ${PLUGIN_TEMP})
# header files for plugins are not usually needed, but find them anyway if they are present
set(OGRE2_PLUGIN_PATH_SUFFIXES
PlugIns
PlugIns/${PLUGIN_NAME}
Plugins
Plugins/${PLUGIN_NAME}
${PLUGIN}
RenderSystems
RenderSystems/${PLUGIN_NAME}
${ARGN})
find_path(
${PREFIX}_INCLUDE_DIR
NAMES
${HEADER}
HINTS
${OGRE2_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE}
PATH_SUFFIXES
${OGRE2_PLUGIN_PATH_SUFFIXES})
find_library(${PREFIX}_LIBRARY
NAMES ${PLUGIN}
HINTS ${OGRE2_LIBRARY_DIRS}
PATH_SUFFIXES "" opt "${OGRE2_SEARCH_VER}" "${OGRE2_SEARCH_VER}/opt")
if (NOT ${PREFIX}_FOUND)
if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY)
set(${PREFIX}_FOUND TRUE)
set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR})
set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY})
message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}")
endif()
endif()
endmacro()
ogre_find_component(Overlay OgreOverlaySystem.h "Overlay")
ogre_find_component(HlmsPbs OgreHlmsPbs.h Hlms/Pbs/)
ogre_find_component(HlmsUnlit OgreHlmsUnlit.h Hlms/Unlit)
ogre_find_plugin(Plugin_ParticleFX OgreParticleFXPrerequisites.h PlugIns/ParticleFX/include)
ogre_find_plugin(RenderSystem_GL3Plus OgreGL3PlusRenderSystem.h RenderSystems/GL3Plus/include)
ogre_find_plugin(RenderSystem_Direct3D11 OgreD3D11RenderSystem.h RenderSystems/Direct3D11/include)
foreach(component ${IgnOGRE2_FIND_COMPONENTS})
set(PREFIX OGRE2_${component})
if(${PREFIX}_FOUND)
set(component_TARGET_NAME "IgnOGRE2-${component}::IgnOGRE2-${component}")
set(component_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS})
# append the Hlms/Common include dir if it exists.
string(FIND ${component} "Hlms" HLMS_POS)
if(${HLMS_POS} GREATER -1)
foreach (dir ${OGRE2_INCLUDE_DIRS})
get_filename_component(dir_name "${dir}" NAME)
if ("${dir_name}" STREQUAL "OGRE-${OGRE2_VERSION_MAJOR}.${OGRE2_VERSION_MINOR}")
set(dir_include "${dir}/Hlms/Common")
if (EXISTS ${dir_include})
list(APPEND component_INCLUDE_DIRS ${dir_include})
endif()
endif()
endforeach()
endif()
set(component_LIBRARIES ${${PREFIX}_LIBRARIES})
ign_import_target(${component}
TARGET_NAME ${component_TARGET_NAME}
LIB_VAR component_LIBRARIES
INCLUDE_VAR component_INCLUDE_DIRS
)
list(APPEND OGRE2_LIBRARIES ${component_TARGET_NAME})
endif()
endforeach()
set(OGRE2_PLUGINS_VCPKG Plugin_ParticleFX RenderSystem_GL3Plus RenderSystem_Direct3D11)
foreach(PLUGIN ${OGRE2_PLUGINS_VCPKG})
if(OGRE2_${PLUGIN}_FOUND)
list(APPEND OGRE2_INCLUDE_DIRS ${OGRE2_${PLUGIN}_INCLUDE_DIRS})
endif()
endforeach()
endif()
endif()
set(IgnOGRE2_FOUND false)
# create OGRE2 target
if (OGRE2_FOUND)
set(IgnOGRE2_FOUND true)
ign_import_target(IgnOGRE2
TARGET_NAME IgnOGRE2::IgnOGRE2
LIB_VAR OGRE2_LIBRARIES
INCLUDE_VAR OGRE2_INCLUDE_DIRS)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindIgnCURL.cmake 0000664 0001750 0001750 00000004010 14160533245 022475 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 curl.
#
# Usage of this module as follows:
#
# find_package(IgnCURL)
#
# Variables defined by this module:
#
# curl::curl Imported target for libcurl
#
# IgnCURL_FOUND System has CURL libs/headers
# IgnCURL_INCLUDE_DIRS The location of CURL headers
# IgnCURL_LIBRARIES The CURL libraries
# IgnCURL_VERSION The version of CURL found
set(ign_quiet_arg)
if(IgnCURL_FIND_QUIETLY)
set(ign_quiet_arg QUIET)
endif()
find_package(CURL ${IgnCURL_FIND_VERSION} ${ign_quiet_arg})
set(IgnCURL_FOUND ${CURL_FOUND})
if(${IgnCURL_FOUND})
set(IgnCURL_INCLUDE_DIRS ${CURL_INCLUDE_DIRS})
set(IgnCURL_LIBRARIES ${CURL_LIBRARIES})
set(IgnCURL_VERSION ${CURL_VERSION_STRING})
# Older versions of curl don't create imported targets, so we will create
# them here if they have not been provided.
if(TARGET CURL::libcurl AND NOT TARGET curl::curl)
add_library(curl::curl INTERFACE IMPORTED)
set_target_properties(curl::curl PROPERTIES
INTERFACE_LINK_LIBRARIES CURL::libcurl)
endif()
include(IgnImportTarget)
if(NOT TARGET curl::curl)
ign_import_target(curl
LIB_VAR CURL_LIBRARIES
INCLUDE_VAR CURL_INCLUDE_DIRS)
endif()
include(IgnPkgConfig)
ign_pkg_config_entry(IgnCURL "libcurl >= ${IgnCURL_FIND_VERSION}")
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnCMake.cmake 0000664 0001750 0001750 00000002605 14160533245 022117 0 ustar jrivero jrivero #.rst
# IgnCMake
# --------
#
# Includes a set of modules that are needed for building the ignition libraries
#
#===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#============================================================================
# ignition-cmake modules
#============================================================================
include(IgnUtils)
include(IgnConfigureProject)
include(IgnPackaging)
include(IgnCreateDocs)
include(IgnSetCompilerFlags)
include(IgnConfigureBuild)
include(IgnImportTarget)
include(IgnPkgConfig)
#============================================================================
# Native cmake modules
#============================================================================
include(CMakePackageConfigHelpers)
include(CMakeParseArguments)
ign-cmake-ignition-cmake2_2.10.0/cmake/FindUUID.cmake 0000664 0001750 0001750 00000004611 14160533245 022047 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 uuid
if (UNIX)
if(NOT APPLE)
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(UUID uuid)
if(NOT UUID_FOUND)
include(IgnManualSearch)
ign_manual_search(UUID
HEADER_NAMES "uuid.h"
LIBRARY_NAMES "uuid libuuid"
PATH_SUFFIXES "uuid")
endif()
# The pkg-config or the manual search will place
# /include/uuid in INTERFACE_INCLUDE_DIRECTORIES,
# but some projects exepect to use /include, so
# we add it as well.
# See https://github.com/ignitionrobotics/ign-cmake/issues/103
if(TARGET UUID::UUID)
get_property(uuid_include_dirs
TARGET UUID::UUID
PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
set(uuid_include_dirs_extended ${uuid_include_dirs})
foreach(include_dir IN LISTS uuid_include_dirs)
if(include_dir MATCHES "uuid$")
get_filename_component(include_dir_parent ${include_dir} DIRECTORY)
list(APPEND uuid_include_dirs_extended ${include_dir_parent})
endif()
endforeach()
list(REMOVE_DUPLICATES uuid_include_dirs_extended)
set_property(
TARGET UUID::UUID
PROPERTY INTERFACE_INCLUDE_DIRECTORIES
${uuid_include_dirs_extended})
endif()
else()
# On Apple platforms the UUID library is provided by the OS SDK
# See https://github.com/ignitionrobotics/ign-cmake/issues/127
set(UUID_FOUND TRUE)
if(NOT TARGET UUID::UUID)
add_library(UUID::UUID INTERFACE IMPORTED)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
UUID
REQUIRED_VARS UUID_FOUND)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindEIGEN3.cmake 0000664 0001750 0001750 00000004167 14160533245 022221 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 EIGEN3
#
# Usage of this module is as follows:
#
# find_package(EIGEN3 [VERSION [.[.]]])
#
# Variables defined by this module:
#
# Eigen3::Eigen Imported target for eigen3
# EIGEN3_FOUND System has eigen3 library and headers
find_package(Eigen3 ${EIGEN3_FIND_VERSION} CONFIG)
if(EIGEN3_FOUND)
# Attempt to create an imported target in case we're using an old version
# of Eigen. (This function skip creating the imported target if it already
# exists).
ign_import_target(EIGEN3 INTERFACE
TARGET_NAME Eigen3::Eigen)
if(EIGEN3_FIND_VERSION)
ign_pkg_config_entry(EIGEN3 "eigen3 >= ${EIGEN3_FIND_VERSION}")
else()
ign_pkg_config_entry(EIGEN3 "eigen3")
endif()
return()
endif()
if(EIGEN3_FIND_VERSION)
ign_pkg_check_modules_quiet(EIGEN3 "eigen3 >= ${EIGEN3_FIND_VERSION}"
INTERFACE
TARGET_NAME Eigen3::Eigen)
else()
ign_pkg_check_modules_quiet(EIGEN3 "eigen3"
INTERFACE
TARGET_NAME Eigen3::Eigen)
endif()
if(MSVC)
set(EIGEN3_FOUND TRUE)
find_path(EIGEN3_INCLUDE_DIRS signature_of_eigen3_matrix_library)
mark_as_advanced(EIGEN3_INCLUDE_DIRS)
if(NOT EIGEN3_INCLUDE_DIRS)
set(EIGEN3_FOUND FALSE)
if(NOT EIGEN3_FIND_QUIETLY)
message(STATUS "Looking for eigen headers (signature_of_eigen3_matrix_library) - not found")
endif()
endif()
ign_import_target(EIGEN3 INTERFACE
TARGET_NAME Eigen3::Eigen)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindAVFORMAT.cmake 0000664 0001750 0001750 00000002141 14160533245 022514 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 AV format
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(AVFORMAT libavformat)
if(NOT AVFORMAT_FOUND)
include(IgnManualSearch)
ign_manual_search(AVFORMAT
HEADER_NAMES "libavformat/avformat.h"
LIBRARY_NAMES "avformat")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
AVFORMAT
REQUIRED_VARS AVFORMAT_FOUND) ign-cmake-ignition-cmake2_2.10.0/cmake/FindIgnProtobuf.cmake 0000664 0001750 0001750 00000007623 14160533245 023545 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 Protobuf
# This is an ignition wrapper for finding Protobuf. The purpose of this find
# module is to search for a config-file for Protobuf before resorting to using
# the native CMake find-module for Protobuf. This ensures that if a specially
# configured version of Protobuf is installed, then its exported targets will be
# correctly imported. This is especially important on Windows in order to
# support shared library versions of Protobuf.
include(IgnPkgConfig)
ign_pkg_config_entry(IgnProtobuf "protobuf >= ${IgnProtobuf_FIND_VERSION}")
find_package(Protobuf ${IgnProtobuf_FIND_VERSION} QUIET CONFIG)
if(NOT ${Protobuf_FOUND})
# If a config-file was not found, then fall back on the system-installed
# find-module that comes with CMake.
find_package(Protobuf ${IgnProtobuf_FIND_VERSION})
endif()
set(IgnProtobuf_missing_components "")
foreach(component ${IgnProtobuf_FIND_COMPONENTS})
# If specific components are requested, check that each one is accounted for.
# If any component is missing, then we should not consider this package to be
# found.
# If a requested component is not required, then we can just skip this
# iteration. We don't do anything special for optional components.
if(NOT IgnProtobuf_FIND_REQUIRED_${component})
continue()
endif()
if((${component} STREQUAL "libprotobuf") OR (${component} STREQUAL "all"))
if((NOT PROTOBUF_LIBRARY) AND (NOT TARGET protobuf::libprotobuf))
set(Protobuf_FOUND false)
ign_string_append(IgnProtobuf_missing_components "libprotobuf" DELIM " ")
endif()
endif()
if((${component} STREQUAL "libprotoc") OR (${component} STREQUAL "all"))
if((NOT PROTOBUF_PROTOC_LIBRARY) AND (NOT TARGET protobuf::libprotoc))
set(Protobuf_FOUND false)
ign_string_append(IgnProtobuf_missing_components "libprotoc" DELIM " ")
endif()
endif()
if((${component} STREQUAL "protoc") OR (${component} STREQUAL "all"))
if((NOT PROTOBUF_PROTOC_EXECUTABLE) AND (NOT TARGET protobuf::protoc))
set(Protobuf_FOUND false)
ign_string_append(IgnProtobuf_missing_components "protoc" DELIM " ")
endif()
endif()
endforeach()
if(IgnProtobuf_missing_components AND NOT IgnProtobuf_FIND_QUIETLY)
message(STATUS "Missing required protobuf components: ${IgnProtobuf_missing_components}")
endif()
if(${Protobuf_FOUND})
# If we have found Protobuf, then set the IgnProtobuf_FOUND flag to true so
# that ign_find_package(~) knows that we were successful.
set(IgnProtobuf_FOUND true)
# Older versions of protobuf don't create imported targets, so we will create
# them here if they have not been provided.
include(IgnImportTarget)
if(NOT TARGET protobuf::libprotobuf)
ign_import_target(protobuf
TARGET_NAME protobuf::libprotobuf
LIB_VAR PROTOBUF_LIBRARY
INCLUDE_VAR PROTOBUF_INCLUDE_DIR)
endif()
if(NOT TARGET protobuf::libprotoc)
ign_import_target(protobuf
TARGET_NAME protobuf::libprotoc
LIB_VAR PROTOBUF_PROTOC_LIBRARY
INCLUDE_VAR PROTOBUF_INCLUDE_DIR)
endif()
if(NOT TARGET protobuf::protoc)
add_executable(protobuf::protoc IMPORTED)
set_target_properties(protobuf::protoc PROPERTIES
IMPORTED_LOCATION ${PROTOBUF_PROTOC_EXECUTABLE})
endif()
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindODE.cmake 0000664 0001750 0001750 00000003736 14160533245 021717 0 ustar jrivero jrivero #===============================================================================
# Base Io build system
# Originally written by there.exists.teslos
# Heavily modified by Open Source Robotics Foundation
#
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 ODE Open Dynamics Engine
find_path(ODE_INCLUDE_DIR ode/ode.h
/usr/include
/usr/local/include
)
set(ODE_NAMES ${ODE_NAMES} ode libode)
find_library(ODE_LIBRARIES NAMES ${ODE_NAMES} PATH)
if(NOT ODE_FIND_QUIETLY)
if(ODE_INCLUDE_DIR)
message(STATUS "Found ODE include dir: ${ODE_INCLUDE_DIR}")
else(ODE_INCLUDE_DIR)
message(STATUS "Couldn't find ODE include dir: ${ODE_INCLUDE_DIR}")
endif(ODE_INCLUDE_DIR)
if(ODE_LIBRARIES)
message(STATUS "Found ODE library: ${ODE_LIBRARIES}")
else(ODE_LIBRARIES)
message(STATUS "Couldn't find ODE library: ${ODE_LIBRARIES}")
endif(ODE_LIBRARIES)
endif()
if(ODE_INCLUDE_DIR AND ODE_LIBRARIES)
set(ODE_FOUND true)
endif(ODE_INCLUDE_DIR AND ODE_LIBRARIES)
if(ODE_FOUND)
if(NOT ODE_FIND_QUIETLY)
message(STATUS "Looking for Open Dynamics Engine - found")
endif()
include(IgnImportTarget)
ign_import_target(ODE)
if(NOT ODE_FIND_QUIETLY)
message(STATUS "Found ODE: ${ODE_LIBRARIES}")
endif(NOT ODE_FIND_QUIETLY)
endif(ODE_FOUND)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
ODE
REQUIRED_VARS ODE_FOUND)
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnPkgConfig.cmake 0000664 0001750 0001750 00000022134 14160533245 023005 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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.
#
########################################
# An alternative to pkg_check_modules that creates an "imported target" which
# helps us to make relocatable packages.
#
# NOTE: This macro assumes that pkg-config is the only means by which you will
# be searching for the package. If you intend to continue searching in the
# event that pkg-config fails (or is unavailable), then you should instead
# call ign_pkg_check_modules_quiet(~).
#
# NOTE: If you need to specify a version comparison for pkg-config, then your
# second argument must be wrapped in quotes. E.g. if you want to find
# version greater than or equal to 3.2.1 of a package called SomePackage
# which is known to pkg-config as libsomepackage, then you should call
# ign_pkg_check_modules as follows:
#
# ign_pkg_check_modules(SomePackage "libsomepackage >= 3.2.1")
#
# The quotes and spaces in the second argument are all very important in
# order to ensure that our auto-generated *.pc file gets filled in
# correctly. If you do not have any version requirements, then you can
# simply leave all of that out:
#
# ign_pkg_check_modules(SomePackage libsomepackage)
#
# Without the version comparison, the quotes and spacing are irrelevant.
# This usage note applies to ign_pkg_check_modules_quiet(~) as well.
#
macro(ign_pkg_check_modules package signature)
ign_pkg_check_modules_quiet(${package} "${signature}" ${ARGN})
if(NOT PKG_CONFIG_FOUND)
message(WARNING "The package [${package}] requires pkg-config in order to be found. "
"Please install pkg-config so we can search for that package.")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
${package}
REQUIRED_VARS ${package}_FOUND)
endmacro()
# This is an alternative to ign_pkg_check_modules(~) which you can use if you
# have an alternative way to look for the package if pkg-config is not available
# or cannot find the requested package. This will still setup the pkg-config
# variables for you, whether or not pkg-config is available.
#
# For usage instructions, see ign_pkg_check_modules(~) above.
macro(ign_pkg_check_modules_quiet package signature)
#------------------------------------
# Define the expected arguments
set(options INTERFACE NO_CMAKE_ENVIRONMENT_PATH QUIET)
set(oneValueArgs "TARGET_NAME")
set(multiValueArgs)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_pkg_check_modules "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ign_pkg_check_modules_INTERFACE)
set(_ign_pkg_check_modules_interface_option INTERFACE)
else()
set(_ign_pkg_check_modules_interface_option) # Intentionally blank
endif()
if(NOT ign_pkg_check_modules_TARGET_NAME)
set(ign_pkg_check_modules_TARGET_NAME "${package}::${package}")
endif()
find_package(PkgConfig QUIET)
ign_pkg_config_entry(${package} "${signature}")
if(PKG_CONFIG_FOUND)
if(${ign_pkg_check_modules_NO_CMAKE_ENVIRONMENT_PATH})
set(ign_pkg_check_modules_no_cmake_environment_path_arg
NO_CMAKE_ENVIRONMENT_PATH)
else()
set(ign_pkg_check_modules_no_cmake_environment_path_arg)
endif()
if(${ign_pkg_check_modules_QUIET} OR ${package}_FIND_QUIETLY)
set(ign_pkg_check_modules_quiet_arg QUIET)
else()
set(ign_pkg_check_modules_quiet_arg)
endif()
pkg_check_modules(${package}
${ign_pkg_check_modules_quiet_arg}
${ign_pkg_check_modules_no_cmake_environment_path_arg}
${signature})
# TODO: When we require cmake-3.6+, we should remove this procedure and just
# use the plain pkg_check_modules, which provides an option called
# IMPORTED_TARGET that will create the imported targets the way we do
# here.
if(${package}_FOUND AND NOT TARGET ${ign_pkg_check_modules_TARGET_NAME})
# Because of some idiosyncrasies of pkg-config, pkg_check_modules does not
# put /usr/include in the _INCLUDE_DIRS variable. E.g. try running
# $ pkg-config --cflags-only-I tinyxml2
# and you'll find that it comes out blank. This blank value gets cached
# into the _INCLUDE_DIRS variable even though it's a bad value. If
# other packages then try to call find_path(_INCLUDE_DIRS ...) in
# their own find-module or config-files, the find_path will quit early
# because a CACHE entry exists for _INCLUDE_DIRS. However, that
# CACHE entry is blank, and so it will typically be interpreted as a
# failed attempt to find the path. So if this _INCLUDE_DIRS
# variable is blank, then we'll unset it from the CACHE to avoid
# conflicts and confusion.
#
# TODO(MXG): Consider giving a different prefix (e.g. IGN_PC_${package})
# to pkg_check_modules(~) so that the cached variables don't collide. That
# would also help with the next TODO below.
if(NOT ${package}_INCLUDE_DIRS)
unset(${package}_INCLUDE_DIRS CACHE)
endif()
# pkg_check_modules will put ${package}_FOUND into the CACHE, which would
# prevent our FindXXX.cmake script from being entered the next time cmake
# is run by a dependent project. This is a problem for us because we
# produce an imported target which gets wiped out and needs to recreated
# between runs.
#
# TODO: Investigate if there is a more conventional solution to this
# problem. Perhaps the cmake-3.6 version of pkg_check_modules has a
# better solution.
unset(${package}_FOUND CACHE)
set(${package}_FOUND TRUE)
# For some reason, pkg_check_modules does not provide complete paths to the
# libraries it returns, even though find_package is conventionally supposed
# to provide complete library paths. Having only the library name is harmful
# to the ign_create_imported_target macro, so we will change the variable to
# give it complete paths.
#
# TODO: How would we deal with multiple modules that are in different
# directories? How does cmake-3.6+ handle that situation?
_ign_pkgconfig_find_libraries(
${package}_LIBRARIES
${package}
"${${package}_LIBRARIES}"
"${${package}_LIBRARY_DIRS}")
include(IgnImportTarget)
ign_import_target(${package} ${_ign_pkg_check_modules_interface_option}
TARGET_NAME ${ign_pkg_check_modules_TARGET_NAME})
endif()
endif()
endmacro()
# This creates variables which inform ign_find_package(~) that your package
# should be found as a module by pkg-config. In most cases, this will be called
# implicitly by ign_pkg_check_modules[_quiet], but if a package provides both a
# cmake config-file (*-config.cmake) and a pkg-config file (*.pc), then you can
# use the cmake config-file to retrieve the package information, and then use
# this macro to generate the relevant pkg-config information.
macro(ign_pkg_config_entry package string)
set(${package}_PKGCONFIG_ENTRY "${string}")
set(${package}_PKGCONFIG_TYPE PKGCONFIG_REQUIRES)
endmacro()
# This creates variables which inform ign_find_package(~) that your package must
# be found as a plain library by pkg-config. This should be used in any
# find-module that handles a library package which does not install a pkg-config
# .pc file.
macro(ign_pkg_config_library_entry package lib_name)
set(${package}_PKGCONFIG_ENTRY "-l${lib_name}")
set(${package}_PKGCONFIG_TYPE PKGCONFIG_LIBS)
endmacro()
# Based on discussion here: https://cmake.org/Bug/view.php?id=15804
# and a patch written by Sam Thursfield
function(_ign_pkgconfig_find_libraries output_var package library_names library_dirs)
foreach(libname ${library_names})
# As recommended in cmake's find_library documenation, we can call
# find_library multiple times with the NO_* option to override search order.
# Give priority to path specified by user by telling cmake not to look
# in default paths. If the first call succeeds, the second call will not
# search again
find_library(
${package}_LIBRARY_${libname}
${libname}
PATHS ${library_dirs} NO_DEFAULT_PATH)
find_library(
${package}_LIBRARY_${libname}
${libname}
PATHS ${library_dirs})
mark_as_advanced(${package}_LIBRARY_${libname})
list(APPEND library_paths "${${package}_LIBRARY_${libname}}")
endforeach()
set(${output_var} ${library_paths} PARENT_SCOPE)
endfunction()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnCodeCheck.cmake 0000664 0001750 0001750 00000003720 14160533245 022746 0 ustar jrivero jrivero # Setup the codecheck target, which will run cppcheck and cppplint.
function(ign_setup_target_for_codecheck)
include(IgnPython)
find_program(CPPCHECK_PATH cppcheck)
find_program(FIND_PATH find)
if(NOT CPPCHECK_PATH)
message(STATUS "The program [cppcheck] was not found! Skipping codecheck setup")
return()
endif()
if(NOT FIND_PATH)
message(STATUS "The program [find] was not found! Skipping codecheck setup.")
return()
endif()
# Base set of cppcheck option
set (CPPCHECK_BASE -q --inline-suppr -j 4 --language=c++ --std=c++14 --force)
if (EXISTS "${PROJECT_BINARY_DIR}/cppcheck.suppress")
set (CPPCHECK_BASE ${CPPCHECK_BASE} --suppressions-list=${PROJECT_BINARY_DIR}/cppcheck.suppress)
endif()
# Extra cppcheck option
set (CPPCHECK_EXTRA --enable=style,performance,portability,information)
# Rules for cppcheck
set (CPPCHECK_RULES "-UM_PI --rule-file=${IGNITION_CMAKE_CODECHECK_DIR}/header_guard.rule --rule-file=${IGNITION_CMAKE_CODECHECK_DIR}/namespace_AZ.rule")
# The find command
set (CPPCHECK_FIND ${FIND_PATH} ${CPPCHECK_DIRS} -name '*.cc' -o -name '*.hh' -o -name '*.c' -o -name '*.h')
message(STATUS "Adding codecheck target")
# Each include directory needs an -I flag
set(CPPCHECK_INCLUDE_DIRS_FLAGS)
foreach(dir ${CPPCHECK_INCLUDE_DIRS})
list(APPEND CPPCHECK_INCLUDE_DIRS_FLAGS "-I${dir}")
endforeach()
add_custom_target(cppcheck
# First cppcheck
COMMAND ${CPPCHECK_PATH} ${CPPCHECK_BASE} ${CPPCHECK_EXTRA} ${CPPCHECK_INCLUDE_DIRS_FLAGS} ${CPPCHECK_RULES} `${CPPCHECK_FIND}`
# Second cppcheck
COMMAND ${CPPCHECK_PATH} ${CPPCHECK_BASE} --enable=missingInclude `${CPPCHECK_FIND}`
)
add_custom_target(codecheck
DEPENDS cppcheck
)
if(PYTHONINTERP_FOUND)
add_custom_target(cpplint
COMMAND ${PYTHON_EXECUTABLE} ${IGNITION_CMAKE_CODECHECK_DIR}/cpplint.py --extensions=cc,hh --quiet `${CPPCHECK_FIND}`
)
add_dependencies(codecheck cpplint)
endif()
endfunction()
ign-cmake-ignition-cmake2_2.10.0/cmake/ignition-config.cmake.in 0000664 0001750 0001750 00000016073 14160533245 024175 0 ustar jrivero jrivero # - Config file for the @PKG_NAME@ package.
#
# For finding and loading @PKG_NAME@ from your project, type:
#
# find_package(@PKG_NAME@)
#
# This creates the following targets:
#
# Core library target - @import_target_name@
# Alternative target name - @simple_import_name@
# Core library + all requested components - @ign_namespace@requested
#
# Use target_link_libraries() to link your library or executable to one of the
# above targets.
#
# We also provide the following variables for backwards compatibility, but use
# of these is discouraged:
#
# @PKG_NAME@_CORE_LIBRARY - Core library (actually contains @simple_import_name@)
# @PKG_NAME@_LIBRARIES - All libraries to link against (actually contains @ign_namespace@requested).
# @PKG_NAME@_INCLUDE_DIRS - Include directories for @PKG_NAME@ and its dependencies.
#
# We will also set @PKG_NAME@_FOUND to indicate that the package was found.
#
################################################################################
# We explicitly set the desired cmake version to ensure that the policy settings
# of users or of toolchains do not result in the wrong behavior for our modules.
# Note that the call to find_package(~) will PUSH a new policy stack before
# taking on these version settings, and then that stack will POP after the
# find_package(~) has exited, so this will not affect the cmake policy settings
# of a caller.
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
if(NOT @PKG_NAME@_FIND_QUIETLY)
message(STATUS "Looking for @PKG_NAME@ -- found version @PROJECT_VERSION_FULL@")
endif()
if(@PKG_NAME@_CONFIG_INCLUDED)
# Check that each of the components requested in this call to find_package(~)
# have already been found.
set(@PKG_NAME@_all_requested_components_found true)
foreach(component ${@PKG_NAME@_FIND_COMPONENTS})
if(NOT @PKG_NAME@-${component}_FOUND)
set(@PKG_NAME@_all_requested_components_found false)
break()
endif()
endforeach()
# If this @PKG_NAME@-config.cmake file has been called before,
# and all the requested components are already found, then exit early.
if(@PKG_NAME@_all_requested_components_found)
return()
endif()
endif()
set(@PKG_NAME@_CONFIG_INCLUDED TRUE)
# Get access to the find_dependency utility
include(CMakeFindDependencyMacro)
# Find ignition-cmake, because we need its modules in order to find the rest of
# our dependencies.
find_dependency(ignition-cmake@IGNITION_CMAKE_VERSION_MAJOR@)
# Set the REQUIRED flag for the find_package(~) calls on this project's
# dependencies.
if(@PKG_NAME@_FIND_REQUIRED)
set(ign_package_required REQUIRED)
else()
set(ign_package_required "")
endif()
# Set the QUIET flag for the find_package(~) calls on this project's
# dependencies.
if(@PKG_NAME@_FIND_QUIETLY)
set(ign_package_quiet QUIET)
else()
set(ign_package_quiet "")
endif()
# --------------------------------
# Find each required dependency of this project (if nothing is below, then the
# project has no external dependencies). We use find_package(~) instead of
# find_dependency(~) here so that we can support COMPONENT arguments.
#
# TODO: When we migrate to cmake-3.9+, change these to find_dependency(~),
# because at that point the find_dependency(~) function will support
# the COMPONENT argument.
if(NOT @PKG_NAME@_FIND_QUIETLY)
message(STATUS "Searching for dependencies of @PKG_NAME@")
endif()
@PROJECT_CMAKE_DEPENDENCIES@
# --------------------------------
@PACKAGE_INIT@
if(NOT TARGET @import_target_name@)
include("${CMAKE_CURRENT_LIST_DIR}/@target_output_filename@")
# Create a simplified imported target name for the core library.
# You can link to this target instead of the core library.
add_library(@simple_import_name@ INTERFACE IMPORTED)
set_target_properties(@simple_import_name@ PROPERTIES
INTERFACE_LINK_LIBRARIES @import_target_name@)
# Note: In a future version of cmake, we can replace this with an ALIAS target
# In case someone tries to link against the plain library name, we want to
# intercept that and have them link against a target instead. This is
# effectively the same as @simple_import_name@, but it does not have the
# benefit of unambiguously being a target name.
add_library(@PKG_NAME@ INTERFACE IMPORTED)
set_target_properties(@PKG_NAME@ PROPERTIES
INTERFACE_LINK_LIBRARIES @import_target_name@)
endif()
# Create the "all" target if it does not already exist
if(NOT TARGET @ign_namespace@requested)
add_library(@ign_namespace@requested INTERFACE IMPORTED)
endif()
# Link the core library to the "all" target. We set the property explicitly
# because target_link_libraries cannot be called on an imported target.
get_target_property(ign_all_components @ign_namespace@requested INTERFACE_LINK_LIBRARIES)
if(NOT ign_all_components)
# If @ign_namespace@requested has not been given any libraries yet, then cmake will
# set ign_all_components to ign_all_components-NOTFOUND, which is something we
# should NOT pass into the INTERFACE_LINK_LIBRARIES property.
set_target_properties(@ign_namespace@requested PROPERTIES
INTERFACE_LINK_LIBRARIES "@import_target_name@")
else()
set_target_properties(@ign_namespace@requested PROPERTIES
INTERFACE_LINK_LIBRARIES "${ign_all_components};@import_target_name@")
endif()
# Package variables. Note that @PKG_NAME@_LIBRARIES and @PKG_NAME@_CORE_LIBRARY
# contain imported targets, so @PKG_NAME@_INCLUDE_DIRS is never needed.
set(@PKG_NAME@_CORE_LIBRARY @simple_import_name@)
set(@PKG_NAME@_LIBRARIES @ign_namespace@requested)
set_and_check(@PKG_NAME@_INCLUDE_DIRS "@PACKAGE_IGN_INCLUDE_INSTALL_DIR_FULL@")
# Backwards compatibility variables
set(@LEGACY_PROJECT_PREFIX@_LIBRARIES ${@PKG_NAME@_LIBRARIES})
set(@LEGACY_PROJECT_PREFIX@_INCLUDE_DIRS ${@PKG_NAME@_INCLUDE_DIRS})
# This macro is used by ignition-cmake to automatically configure the pkgconfig
# files for ignition projects.
ign_pkg_config_entry(@PKG_NAME@ "@PKG_NAME@")
# Find each of the components requested by find_package(~)
foreach(component ${@PKG_NAME@_FIND_COMPONENTS})
if(NOT @PKG_NAME@_FIND_QUIETLY)
message(STATUS "Searching for <@PKG_NAME@> component [${component}]")
endif()
if(@PKG_NAME@_FIND_REQUIRED_${component})
# Find the component package using find_dependency(~). If the user specified
# REQUIRED or QUIET, those will automatically get forwarded to
# find_dependency(~)
find_dependency(@PKG_NAME@-${component} @PROJECT_VERSION_FULL_NO_SUFFIX@ EXACT)
else()
# If this is an optional component, use find_package(~) instead of
# find_dependency(~) so we can ensure that the use of REQUIRED does not get
# forwarded to it.
find_package(@PKG_NAME@-${component} @PROJECT_VERSION_FULL_NO_SUFFIX@ EXACT ${ign_package_quiet})
endif()
endforeach()
# Specify the doxygen tag file
set(@PROJECT_NAME_NO_VERSION_UPPER@_DOXYGEN_TAGFILE "${PACKAGE_PREFIX_DIR}/@IGN_DATA_INSTALL_DIR@/@PROJECT_NAME_LOWER@.tag.xml")
# Specify the API url. This is where the doxygen tag file will resolve URLS to.
set(@PROJECT_NAME_NO_VERSION_UPPER@_API_URL "https://ignitionrobotics.org/api/@IGN_DESIGNATION@/@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@")
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnCodeCoverage.cmake 0000664 0001750 0001750 00000013521 14160533245 023464 0 ustar jrivero jrivero #
# 2012-01-31, Lars Bilke
# - Enable Code Coverage
#
# 2013-09-17, Joakim Söderberg
# - Added support for Clang.
# - Some additional usage instructions.
#
# 2017-09-13
# - Tweaked instructions for ignition libraries
# - Tweaked function name to avoid name collisions
#
# USAGE:
# 1. Add the following line to your CMakeLists.txt:
# INCLUDE(IgnCodeCoverage)
#
# 2. Set compiler flags to turn off optimization and enable coverage:
# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
#
# 3. Use the function IGN_SETUP_TARGET_FOR_COVERAGE to create a custom make target
# which runs your test executable and produces a lcov code coverage report:
# Example:
# IGN_SETUP_TARGET_FOR_COVERAGE(
# my_coverage_target # Name for custom target.
# test_driver # Name of the test driver executable that runs the tests.
# # NOTE! This should always have a ZERO as exit code
# # otherwise the coverage generation will not complete.
# coverage # Name of output directory.
# )
#
# 4. Build a Coverge build:
# cmake -DCMAKE_BUILD_TYPE=Coverage ..
# make
# make my_coverage_target
#
#
# Check prereqs
FIND_PROGRAM( GCOV_PATH gcov )
FIND_PROGRAM( LCOV_PATH lcov )
FIND_PROGRAM( GREP_PATH grep )
FIND_PROGRAM( GENHTML_PATH genhtml )
FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
IF(NOT GCOV_PATH)
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
ENDIF() # NOT GCOV_PATH
IF(NOT CMAKE_COMPILER_IS_GNUCXX)
# Clang version 3.0.0 and greater now supports gcov as well.
MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
IF(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
ENDIF()
ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX
IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage"))
MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" )
ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
#################################################
# ign_setup_target_for_coverage(
# [BRANCH_COVERAGE]
# [OUTPUT_NAME ]
# [TARGET_NAME ]
# [TEST_RUNNER ])
#
# This function will create custom coverage targets with the specified options.
#
# Coverage is not run for files in the following formats:
#
# *.cxx : We assume these files are created by swig.
# moc_*.cpp and qrc_*.cpp : We assume these files are created by Qt's meta-object compiler.
#
# BRANCH_COVERAGE: Optional. If provided, branch coverage will be computed
# instead of line coverage.
#
# OUTPUT_NAME: Required.
# lcov output is generated as _outputname.info
# HTML report is generated in _outputname/index.html
#
# TARGET_NAME: The name of new the custom make target.
#
# TEST_RUNNER: The name of the target which runs the tests.
# MUST return ZERO always, even on errors.
# If not, no coverage report will be created!
#
FUNCTION(ign_setup_target_for_coverage)
#------------------------------------
# Define the expected arguments
set(options "BRANCH_COVERAGE")
set(oneValueArgs "OUTPUT_NAME" "TARGET_NAME" "TEST_RUNNER")
set(multiValueArgs)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(_outputname ${ign_coverage_OUTPUT_NAME})
set(_targetname ${ign_coverage_TARGET_NAME})
set(_testrunner ${ign_coverage_TEST_RUNNER})
if(ign_coverage_BRANCH_COVERAGE)
set(_branch_flags --rc lcov_branch_coverage=1)
endif()
IF(NOT LCOV_PATH)
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
ENDIF() # NOT LCOV_PATH
IF(NOT GREP_PATH)
MESSAGE(FATAL_ERROR "grep not found! Run code coverage on linux or mac.")
ENDIF()
IF(NOT GENHTML_PATH)
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
ENDIF() # NOT GENHTML_PATH
# Setup target
ADD_CUSTOM_TARGET(${_targetname}
COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info.cleaned
${_outputname}.info
# Capturing lcov counters and generating report
COMMAND ${LCOV_PATH} ${_branch_flags} -q --no-checksum
--directory ${PROJECT_BINARY_DIR} --capture
--output-file ${_outputname}.info 2>/dev/null
# Remove negative counts
COMMAND sed -i '/,-/d' ${_outputname}.info
COMMAND ${LCOV_PATH} ${_branch_flags} -q
--remove ${_outputname}.info '*/test/*' '/usr/*' '*_TEST*' '*.cxx' 'moc_*.cpp' 'qrc_*.cpp' --output-file ${_outputname}.info.cleaned
COMMAND ${GENHTML_PATH} ${_branch_flags} -q
--legend -o ${_outputname} ${_outputname}.info.cleaned
COMMAND ${LCOV_PATH} --summary ${_outputname}.info.cleaned 2>&1 | grep "lines" | cut -d ' ' -f 4 | cut -d '%' -f 1 > ${_outputname}/lines.txt
COMMAND ${LCOV_PATH} --summary ${_outputname}.info.cleaned 2>&1 | grep "functions" | cut -d ' ' -f 4 | cut -d '%' -f 1 > ${_outputname}/functions.txt
COMMAND ${LCOV_PATH} ${_branch_flags}
--summary ${_outputname}.info.cleaned 2>&1 | grep "branches" | cut -d ' ' -f 4 | cut -d '%' -f 1 > ${_outputname}/branches.txt
COMMAND ${CMAKE_COMMAND} -E rename ${_outputname}.info.cleaned
${_outputname}.info
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Resetting code coverage counters to zero.\n"
"Processing code coverage counters and generating report."
)
# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
COMMAND COMMAND ${LCOV_PATH} -q --zerocounters --directory ${PROJECT_BINARY_DIR};
COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
)
ENDFUNCTION() # IGN_SETUP_TARGET_FOR_COVERAGE
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnManualSearch.cmake 0000664 0001750 0001750 00000007012 14160533245 023477 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2020 Open Source Robotics Foundation
#
# Licensed 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.
#
########################################
# ign_manual_search( [INTERFACE]
# [HEADER_NAMES ]
# [LIBRARY_NAMES ]
# [TARGET_NAME ]
# [PATH_SUFFIXES ]])
#
# This macro will find a library based on the name of one of its headers,
# and the library name.
# It is used inside Find***.cmake scripts, typicall as fallback for a
# ign_pkg_check_modules_quiet call.
# It will create an imported target for the library
#
# INTERFACE: Optional. Use INTERFACE when the target does not actually provide
# a library that needs to be linked against (e.g. it is a header-only
# library, or the target is just used to specify compiler flags).
#
# HEADER_NAMES: Optional. Explicitly specify the header names to search with find_path.
# Default is .h.
#
# LIBRARY_NAMES: Optional. Explicitly specify the names of the library to search with find_library.
# Default is .
#
# TARGET_NAME: Optional. Explicitly specify the desired imported target name.
# Default is ::.
#
# PATH_SUFFIXES: Optional. Parameter forwarded to the find_path and find_library calls.
#
macro(ign_manual_search package)
#------------------------------------
# Define the expected arguments
set(options INTERFACE)
set(oneValueArgs "TARGET_NAME")
set(multiValueArgs "HEADER_NAMES" "LIBRARY_NAMES" "PATH_SUFFIXES")
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_manual_search "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ign_manual_search_INTERFACE)
set(_ign_manual_search_interface_option INTERFACE)
else()
set(_ign_manual_search_interface_option) # Intentionally blank
endif()
if(NOT ign_manual_search_HEADER_NAMES)
set(ign_manual_search_HEADER_NAMES "${package}.h")
endif()
if(NOT ign_manual_search_LIBRARY_NAMES)
set(ign_manual_search_LIBRARY_NAMES "${package}")
endif()
if(NOT ign_manual_search_TARGET_NAME)
set(ign_manual_search_TARGET_NAME "${package}::${package}")
endif()
find_path(${package}_INCLUDE_DIRS
NAMES ${ign_manual_search_HEADER_NAMES}
PATH_SUFFIXES ${ign_manual_search_PATH_SUFFIXES})
find_library(${package}_LIBRARIES
NAMES ${ign_manual_search_LIBRARY_NAMES}
PATH_SUFFIXES ${ign_manual_search_PATH_SUFFIXES})
mark_as_advanced(${package}_INCLUDE_DIRS)
mark_as_advanced(${package}_LIBRARIES)
set(${package}_FOUND true)
if(NOT ${package}_INCLUDE_DIRS)
set(${package}_FOUND false)
endif()
if(NOT ${package}_LIBRARIES)
set(${package}_FOUND false)
endif()
if(${package}_FOUND)
include(IgnImportTarget)
ign_import_target(${package} ${_ign_pkg_check_modules_interface_option}
TARGET_NAME ${ign_pkg_check_modules_TARGET_NAME})
endif()
endmacro()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindOptiX.cmake 0000664 0001750 0001750 00000021607 14160533245 022350 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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.
#
########################################
# Modified from NVIDIA's FindOptiX.cmake distributed in its OptiX SDK
# Usage of this module as follows:
#
# ign_find_package(OptiX)
#
# Variable used by this module, which needs to be set before calling
# find_package:
#
# OPTIX_INSTALL_DIR Set this variable to the root installation of
# OptiX SDK
#
# Variables defined by this module:
#
# optix::optix Imported target for optix
# optix::optixu Imported target for optixu
# optix::optix_prime Imported target for optix_prime
#
# OptiX_FOUND System has OptiX libs/headers
# OptiX_LIBRARIES The OptiX libraries
# OptiX_INCLUDE_DIRS The location of OptiX headers
#
########################################
#
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Locate the OptiX distribution. Search in env path first, then look in the system.
set(OptiX_INSTALL_DIR "$ENV{OPTIX_INSTALL_DIR}" CACHE PATH "Path to OptiX installed location.")
# The distribution contains both 32 and 64 bit libraries. Adjust the library
# search path based on the bit-ness of the build. (i.e. 64: bin64, lib64; 32:
# bin, lib). Note that on Mac, the OptiX library is a universal binary, so we
# only need to look in lib and not lib64 for 64 bit builds.
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT APPLE)
set(bit_dest "64")
else()
set(bit_dest "")
endif()
# ign-cmake modification: added "ign_" prefix to macro name
macro(ign_OPTIX_find_api_library name version)
find_library(${name}_LIBRARY
NAMES ${name}.${version} ${name}
PATHS "${OptiX_INSTALL_DIR}/lib${bit_dest}"
NO_DEFAULT_PATH
)
find_library(${name}_LIBRARY
NAMES ${name}.${version} ${name}
)
if(WIN32)
find_file(${name}_DLL
NAMES ${name}.${version}.dll
PATHS "${OptiX_INSTALL_DIR}/bin${bit_dest}"
NO_DEFAULT_PATH
)
find_file(${name}_DLL
NAMES ${name}.${version}.dll
)
endif()
endmacro()
ign_OPTIX_find_api_library(optix 1)
ign_OPTIX_find_api_library(optixu 1)
ign_OPTIX_find_api_library(optix_prime 1)
# Include
find_path(OptiX_INCLUDE
NAMES optix.h
PATHS "${OptiX_INSTALL_DIR}/include"
NO_DEFAULT_PATH
)
find_path(OptiX_INCLUDE
NAMES optix.h
)
# Check to make sure we found what we were looking for
function(OptiX_report_error error_message required)
if(OptiX_FIND_REQUIRED AND required)
message(FATAL_ERROR "${error_message}")
else()
if(NOT OptiX_FIND_QUIETLY)
message(STATUS "${error_message}")
endif(NOT OptiX_FIND_QUIETLY)
endif()
endfunction()
if(NOT optix_LIBRARY)
OptiX_report_error("optix library not found. Please locate before proceeding." TRUE)
endif()
if(NOT OptiX_INCLUDE)
OptiX_report_error("OptiX headers (optix.h and friends) not found. Please locate before proceeding." TRUE)
endif()
if(NOT optix_prime_LIBRARY)
OptiX_report_error("optix Prime library not found. Please locate before proceeding." FALSE)
endif()
# Macro for setting up dummy targets
function(OptiX_add_imported_library name lib_location dll_lib dependent_libs)
set(CMAKE_IMPORT_FILE_VERSION 1)
# Create imported target
# ign-cmake modification: changed to use ${target_name} instead of ${name}
set(target_name optix::${name})
add_library(${target_name} SHARED IMPORTED)
# Import target "optix" for configuration "Debug"
if(WIN32)
set_target_properties(${target_name} PROPERTIES
IMPORTED_IMPLIB "${lib_location}"
#IMPORTED_LINK_INTERFACE_LIBRARIES "glu32;opengl32"
IMPORTED_LOCATION "${dll_lib}"
IMPORTED_LINK_INTERFACE_LIBRARIES "${dependent_libs}"
)
elseif(UNIX)
set_target_properties(${target_name} PROPERTIES
#IMPORTED_LINK_INTERFACE_LIBRARIES "glu32;opengl32"
IMPORTED_LOCATION "${lib_location}"
# We don't have versioned filenames for now, and it may not even matter.
#IMPORTED_SONAME "${optix_soname}"
IMPORTED_LINK_INTERFACE_LIBRARIES "${dependent_libs}"
)
else()
# Unknown system, but at least try and provide the minimum required
# information.
set_target_properties(${target_name} PROPERTIES
IMPORTED_LOCATION "${lib_location}"
IMPORTED_LINK_INTERFACE_LIBRARIES "${dependent_libs}"
)
endif()
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
endfunction()
# Sets up a dummy target
OptiX_add_imported_library(optix "${optix_LIBRARY}" "${optix_DLL}" "${OPENGL_LIBRARIES}")
OptiX_add_imported_library(optixu "${optixu_LIBRARY}" "${optixu_DLL}" "")
OptiX_add_imported_library(optix_prime "${optix_prime_LIBRARY}" "${optix_prime_DLL}" "")
# ign-cmake modification: added "ign_" prefix to macro name
macro(ign_OptiX_check_same_path libA libB)
if(_optix_path_to_${libA})
if(NOT _optix_path_to_${libA} STREQUAL _optix_path_to_${libB})
# ${libA} and ${libB} are in different paths. Make sure there isn't a ${libA} next
# to the ${libB}.
get_filename_component(_optix_name_of_${libA} "${${libA}_LIBRARY}" NAME)
if(EXISTS "${_optix_path_to_${libB}}/${_optix_name_of_${libA}}")
message(WARNING " ${libA} library found next to ${libB} library that is not being used. Due to the way we are using rpath, the copy of ${libA} next to ${libB} will be used during loading instead of the one you intended. Consider putting the libraries in the same directory or moving ${_optix_path_to_${libB}}/${_optix_name_of_${libA} out of the way.")
endif()
endif()
set( _${libA}_rpath "-Wl,-rpath,${_optix_path_to_${libA}}" )
endif()
endmacro()
# Since liboptix.1.dylib is built with an install name of @rpath, we need to
# compile our samples with the rpath set to where optix exists.
if(APPLE)
get_filename_component(_optix_path_to_optix "${optix_LIBRARY}" PATH)
if(_optix_path_to_optix)
set( _optix_rpath "-Wl,-rpath,${_optix_path_to_optix}" )
endif()
get_filename_component(_optix_path_to_optixu "${optixu_LIBRARY}" PATH)
ign_OptiX_check_same_path(optixu optix)
get_filename_component(_optix_path_to_optix_prime "${optix_prime_LIBRARY}" PATH)
ign_OptiX_check_same_path(optix_prime optix)
ign_OptiX_check_same_path(optix_prime optixu)
set( optix_rpath ${_optix_rpath} ${_optixu_rpath} ${_optix_prime_rpath} )
list(LENGTH optix_rpath optix_rpath_LENGTH)
if (optix_rpath_LENGTH GREATER 0)
list(REMOVE_DUPLICATES optix_rpath)
endif()
endif()
########################################
if (OptiX_INCLUDE AND optix_LIBRARY)
set (OptiX_FOUND TRUE)
else()
set (OptiX_FOUND FALSE)
endif()
if (OptiX_FOUND)
set(OptiX_INCLUDE_DIRS ${OptiX_INCLUDE})
set(OptiX_LIBRARIES ${optix_LIBRARY} ${optixu_LIBRARY} ${optix_prime_LIBRARY})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
OptiX
REQUIRED_VARS OptiX_FOUND)
include(IgnPkgConfig)
ign_pkg_config_library_entry(OptiX OptiX)
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnUtils.cmake 0000664 0001750 0001750 00000212434 14160533245 022242 0 ustar jrivero jrivero
#################################################
# ign_find_package(
# [REQUIRED] [PRIVATE] [EXACT] [QUIET] [BUILD_ONLY] [PKGCONFIG_IGNORE]
# [COMPONENTS ]
# [OPTIONAL_COMPONENTS ]
# [REQUIRED_BY ]
# [PRIVATE_FOR ]
# [VERSION ]
# [EXTRA_ARGS ]
# [PRETTY ]
# [PURPOSE <"explanation for this dependency">]
# [PKGCONFIG ]
# [PKGCONFIG_LIB ]
# [PKGCONFIG_VER_COMPARISON < > = <= >= ])
#
# This is a wrapper for the standard cmake find_package which behaves according
# to the conventions of the ignition library. In particular, we do not quit
# immediately when a required package is missing. Instead, we check all
# dependencies and provide an overview of what is missing at the end of the
# configuration process. Descriptions of the function arguments are as follows:
#
# : The name of the package as it would normally be passed to
# find_package(~). Note if your package corresponds to a
# find-module named FindABC.cmake, then must be
# ABC, with the case matching. If the find-module is named
# FindAbc.cmake, then must be Abc. This will not
# necessarily match the library's actual name, nor will it
# necessarily match the name used by pkgconfig, so there are
# additional arguments (i.e. PRETTY, PKGCONFIG) to specify
# alternative names for this package that can be used depending
# on the context.
#
# [REQUIRED]: Optional. If provided, macro will trigger an ignition build_error
# when the package cannot be found. If not provided, this macro will
# trigger an ignition build_warning when the package is not found.
# To specify that something is required by some set of components
# (rather than the core library), use REQUIRED_BY.
#
# [PRIVATE]: Optional. Use this to indicate that consumers of the project do not
# need to link against the package, but it must be present on the
# system, because our project must link against it.
#
# [EXACT]: Optional. This will pass on the EXACT option to find_package(~) and
# also add it to the call to find_dependency(~) in the
# -config.cmake file.
#
# [QUIET]: Optional. If provided, it will be passed forward to cmake's
# find_package(~) command. This macro will still print its normal
# output, except there will be no warning if the package is missing,
# unless REQUIRED or REQUIRED_BY is specified.
#
# [BUILD_ONLY]: Optional. Use this to indicate that the project only needs this
# package while building, and it does not need to be available to
# the consumer of this project at all. Normally this should only
# apply to (1) a header-only library whose headers are included
# exclusively in the source files and not included in any public
# (i.e. installed) project headers, or to (2) a static library
# dependency.
#
# [PKGCONFIG_IGNORE]: Discouraged. If this option is provided, this package will
# not be added to the project's pkgconfig file in any way.
# This should only be used in very rare circumstances. Note
# that BUILD_ONLY will also prevent a pkgconfig entry from
# being produced.
#
# [COMPONENTS]: Optional. If provided, the list that follows it will be passed
# to find_package(~) to indicate which components of PACKAGE_NAME
# are considered to be dependencies of either this project
# (specified by REQUIRED) or this project's components (specified
# by REQUIRED_BY). This is effectively the same as the
# find_package( ... COMPONENTS ) argument.
#
# [REQUIRED_BY]: Optional. If provided, the list that follows it must indicate
# which library components require the dependency. Note that if
# REQUIRED is specified, then REQUIRED_BY does NOT need to be
# specified for any components which depend on the core library,
# because their dependence on this package will effectively be
# inherited from the core library. This will trigger a build
# warning to tell the user which component requires this
# dependency.
#
# [PRIVATE_FOR]: Optional. If provided, the list that follows it must indicate
# which library components depend on this package privately (i.e.
# the package should not be included in its list of interface
# libraries). This is only relevant for components that follow
# the REQUIRED_BY command. Note that the PRIVATE argument does
# not apply to components specified by REQUIRED_BY. This argument
# MUST be given for components whose private dependencies have
# been specified with REQUIRED_BY.
#
# [VERSION]: Optional. Follow this argument with the major[.minor[.patch[.tweak]]]
# version that you need for this package.
#
# [EXTRA_ARGS]: Optional. Additional args to pass forward to find_package(~)
#
# [PRETTY]: Optional. If provided, the string that follows will replace
# when printing messages, warnings, or errors to the
# terminal.
#
# [PURPOSE]: Optional. If provided, the string that follows will be appended to
# the build_warning or build_error that this function produces when
# the package could not be found.
#
# ==========================================================================
# The following arguments pertain to the automatic generation of your
# project's pkgconfig file. Ideally, this information should be provided
# automatically by ignition-cmake through the cmake find-module that is written
# for your dependency. However, if your package gets distributed with its own
# cmake config-file or find-module, then it might not automatically set this
# information. Therefore, we provide the ability to set it through your call to
# ign_find_package(~). These arguments can also be used to overwrite the
# pkg-config entries that get generated by the ign-cmake find-module for the
# package. Do not hesitate to ask for help if you need to use these arguments.
#
# [PKGCONFIG]: Optional. If provided, the string that follows will be used to
# specify a "required package" for pkgconfig. Note that the option
# PKGCONFIG_LIB has higher precedence than this option.
#
# [PKGCONFIG_LIB]: Optional. Use this to indicate that the package should be
# considered a "library" by pkgconfig. This is used for
# libraries which do not come with *.pc metadata, such as
# system libraries, libm, libdl, or librt. Generally you should
# leave this out, because most packages will be considered
# "modules" by pkgconfig. The string which follows this
# argument will be used as the library name, and the string
# that follows a PKGCONFIG argument will be ignored, so the
# PKGCONFIG argument can be left out when using this argument.
#
# [PKGCONFIG_VER_COMPARISON]: Optional. If provided, pkgconfig will be told how
# the available version of this package must compare
# to the specified version. Acceptable values are
# =, <, >, <=, >=. Default will be =. If no version
# is provided using VERSION, then this will be left
# out, whether or not it is provided.
#
macro(ign_find_package PACKAGE_NAME)
#------------------------------------
# Define the expected arguments
set(options REQUIRED PRIVATE EXACT QUIET BUILD_ONLY PKGCONFIG_IGNORE)
set(oneValueArgs VERSION PRETTY PURPOSE EXTRA_ARGS PKGCONFIG PKGCONFIG_LIB PKGCONFIG_VER_COMPARISON)
set(multiValueArgs REQUIRED_BY PRIVATE_FOR COMPONENTS OPTIONAL_COMPONENTS)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_find_package "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#------------------------------------
# Construct the arguments to pass to find_package
set(${PACKAGE_NAME}_find_package_args ${PACKAGE_NAME})
if(ign_find_package_VERSION)
list(APPEND ${PACKAGE_NAME}_find_package_args ${ign_find_package_VERSION})
endif()
if(ign_find_package_QUIET)
list(APPEND ${PACKAGE_NAME}_find_package_args QUIET)
endif()
if(ign_find_package_EXACT)
list(APPEND ${PACKAGE_NAME}_find_package_args EXACT)
endif()
if(ign_find_package_COMPONENTS)
list(APPEND ${PACKAGE_NAME}_find_package_args COMPONENTS ${ign_find_package_COMPONENTS})
endif()
if(ign_find_package_OPTIONAL_COMPONENTS)
list(APPEND ${PACKAGE_NAME}_find_package_args OPTIONAL_COMPONENTS ${ign_find_package_OPTIONAL_COMPONENTS})
endif()
if(ign_find_package_EXTRA_ARGS)
list(APPEND ${PACKAGE_NAME}_find_package_args ${ign_find_package_EXTRA_ARGS})
endif()
#------------------------------------
# Figure out which name to print
if(ign_find_package_PRETTY)
set(${PACKAGE_NAME}_pretty ${ign_find_package_PRETTY})
else()
set(${PACKAGE_NAME}_pretty ${PACKAGE_NAME})
endif()
#------------------------------------
# Call find_package with the provided arguments
find_package(${${PACKAGE_NAME}_find_package_args})
if(${PACKAGE_NAME}_FOUND)
message(STATUS "Looking for ${${PACKAGE_NAME}_pretty} - found\n")
else()
message(STATUS "Looking for ${${PACKAGE_NAME}_pretty} - not found\n")
#------------------------------------
# Construct the warning/error message to produce
set(${PACKAGE_NAME}_msg "Missing dependency [${${PACKAGE_NAME}_pretty}]")
if(ign_find_package_COMPONENTS)
ign_list_to_string(comp_str ign_find_package_COMPONENTS DELIM ", ")
set(${PACKAGE_NAME}_msg "${${PACKAGE_NAME}_msg} (Components: ${comp_str})")
endif()
if(DEFINED ign_find_package_PURPOSE)
set(${PACKAGE_NAME}_msg "${${PACKAGE_NAME}_msg} - ${ign_find_package_PURPOSE}")
endif()
#------------------------------------
# If the package is unavailable, tell the user.
if(ign_find_package_REQUIRED)
# If it was required by the project, we will create an error.
ign_build_error(${${PACKAGE_NAME}_msg})
elseif(ign_find_package_REQUIRED_BY)
foreach(component ${ign_find_package_REQUIRED_BY})
if(NOT SKIP_${component})
# Otherwise, if it was only required by some of the components, create
# a warning about which components will not be available, unless the
# user explicitly requested that it be skipped
ign_build_warning("Skipping component [${component}]: ${${PACKAGE_NAME}_msg}.\n ^~~~~ Set SKIP_${component}=true in cmake to suppress this warning.\n ")
# Create a variable to indicate that we need to skip the component
set(INTERNAL_SKIP_${component} true)
# Track the missing dependencies
ign_string_append(${component}_MISSING_DEPS "${${PACKAGE_NAME}_pretty}" DELIM ", ")
endif()
endforeach()
else()
if(NOT ign_find_package_QUIET)
ign_build_warning(${${PACKAGE_NAME}_msg})
endif()
endif()
endif()
#------------------------------------
# Add this package to the list of dependencies that will be inserted into the
# find-config file, unless the invoker specifies that it should not be added.
# Also, add this package or library as an entry to the pkgconfig file that we
# will produce for our project.
if( ${PACKAGE_NAME}_FOUND
AND (ign_find_package_REQUIRED OR ign_find_package_REQUIRED_BY)
AND NOT ign_find_package_BUILD_ONLY)
# Set up the arguments we want to pass to the find_dependency invokation for
# our ignition project. We always need to pass the name of the dependency.
#
# NOTE: We escape the dollar signs because we want those variable
# evaluations to be a part of the string that we produce. It is going
# to be put into a *-config.cmake file. Those variables determine
# whether the find_package(~) call will be REQUIRED and/or QUIET.
#
# TODO: When we migrate to cmake-3.9+, this can be removed because calling
# find_dependency(~) will automatically forward these properties.
set(${PACKAGE_NAME}_dependency_args "${PACKAGE_NAME}")
# If a version is provided here, we should pass that as well.
if(ign_find_package_VERSION)
ign_string_append(${PACKAGE_NAME}_dependency_args ${ign_find_package_VERSION})
endif()
# If we have specified the exact version, we should provide that as well.
if(ign_find_package_EXACT)
ign_string_append(${PACKAGE_NAME}_dependency_args EXACT)
endif()
# NOTE (MXG): 7 seems to be the number of escapes required to get
# "${ign_package_required}" and "${ign_package_quiet}" to show up correctly
# as strings in the final config-file outputs. It is unclear to me why the
# escapes get collapsed exactly three times, so it is possible that any
# changes to this script could cause a different number of escapes to be
# necessary. Please use caution when modifying this script.
ign_string_append(${PACKAGE_NAME}_dependency_args "\\\\\\\${ign_package_quiet} \\\\\\\${ign_package_required}")
# If we have specified components of the dependency, mention those.
if(ign_find_package_COMPONENTS)
ign_string_append(${PACKAGE_NAME}_dependency_args "COMPONENTS ${ign_find_package_COMPONENTS}")
endif()
# If there are any additional arguments for the find_package(~) command,
# forward them along.
if(ign_find_package_EXTRA_ARGS)
ign_string_append(${PACKAGE_NAME}_dependency_args "${ign_find_package_EXTRA_ARGS}")
endif()
# TODO: When we migrate to cmake-3.9+ bring back find_dependency(~) because
# at that point it will be able to support COMPONENTS and EXTRA_ARGS
# set(${PACKAGE_NAME}_find_dependency "find_dependency(${${PACKAGE_NAME}_dependency_args})")
set(${PACKAGE_NAME}_find_dependency "find_package(${${PACKAGE_NAME}_dependency_args})")
if(ign_find_package_REQUIRED)
# If this is REQUIRED, add it to PROJECT_CMAKE_DEPENDENCIES
ign_string_append(PROJECT_CMAKE_DEPENDENCIES "${${PACKAGE_NAME}_find_dependency}" DELIM "\n")
endif()
if(ign_find_package_REQUIRED_BY)
# Identify which components are privately requiring this package
foreach(component ${ign_find_package_PRIVATE_FOR})
set(${component}_${PACKAGE_NAME}_PRIVATE true)
endforeach()
# If this is required by some components, add it to the
# ${component}_CMAKE_DEPENDENCIES variables that are specific to those
# componenets
foreach(component ${ign_find_package_REQUIRED_BY})
if(NOT ${component}_${PACKAGE_NAME}_PRIVATE)
ign_string_append(${component}_CMAKE_DEPENDENCIES "${${PACKAGE_NAME}_find_dependency}" DELIM "\n")
endif()
endforeach()
endif()
#------------------------------------
# Add this library or project to its relevant pkgconfig entry, unless we
# have been explicitly instructed to ignore it.
if(NOT ign_find_package_PKGCONFIG_IGNORE)
# Here we will set up the pkgconfig entry for this package. Ordinarily,
# these variables should be set by the ign-cmake custom find-module for
# the package which should use ign_pkg_check_modules[_quiet] or
# ign_pkg_config_library_entry. However, that will not be performed by
# third-party dependencies that provide their own find-module or their own
# cmake config-module. Therefore, we provide the option of specifying
# pkgconfig information through the call to ign_find_package. This also
# allows callers of ign_find_package(~) to overwrite the default
# pkg-config entry that gets generated by the ign-cmake find-modules.
# If the caller has specified the arguments PKGCONFIG_LIB or PKGCONFIG,
# then we will overwrite these pkgconfig variables with the information
# provided by the caller.
if(ign_find_package_PKGCONFIG_LIB)
# Libraries must be prepended with -l
set(${PACKAGE_NAME}_PKGCONFIG_ENTRY "-l${ign_find_package_PKGCONFIG_LIB}")
set(${PACKAGE_NAME}_PKGCONFIG_TYPE PKGCONFIG_LIBS)
elseif(ign_find_package_PKGCONFIG)
# Modules (a.k.a. packages) can just be specified by their package
# name without any prefixes like -l
set(${PACKAGE_NAME}_PKGCONFIG_ENTRY "${ign_find_package_PKGCONFIG}")
set(${PACKAGE_NAME}_PKGCONFIG_TYPE PKGCONFIG_REQUIRES)
# Add the version requirements to the entry.
if(ign_find_package_VERSION)
# Use equivalency by default
set(comparison "=")
# If the caller has specified a version comparison operator, use that
# instead of equivalency.
if(ign_find_package_PKGCONFIG_VER_COMPARISON)
set(comparison ${ign_find_package_PKGCONFIG_VER_COMPARISON})
endif()
# Append the comparison and the version onto the pkgconfig entry
set(${PACKAGE_NAME}_PKGCONFIG_ENTRY "${${PACKAGE_NAME}_PKGCONFIG_ENTRY} ${comparison} ${ign_find_package_VERSION}")
endif()
endif()
if(NOT ${PACKAGE_NAME}_PKGCONFIG_ENTRY)
# The find-module has not provided a default pkg-config entry for this
# package, and the caller of ign_find_package(~) has not explicitly
# provided pkg-config information. The caller has also not specified
# PKGCONFIG_IGNORE. This means that the requirements of this package
# will be unintentionally omitted from the auto-generated
# ignition-.pc file. This is probably an oversight in our build
# system scripts, so we will emit a warning about this.
message(AUTHOR_WARNING
" -- THIS MESSAGE IS INTENDED FOR IGNITION-${IGN_DESIGNATION_UPPER} AUTHORS --\n"
" (IF YOU SEE THIS, PLEASE REPORT IT)\n"
"Could not find pkg-config information for ${PACKAGE_NAME}. "
"It was not provided by the find-module for the package, nor was it "
"explicitly passed into the call to ign_find_package(~). This is "
"most likely an error in this project's use of ign-cmake.")
else()
# We have pkg-config information for this package
if(ign_find_package_REQUIRED)
if(ign_find_package_PRIVATE)
# If this is a private library or module, use the _PRIVATE suffix
set(PROJECT_${PACKAGE_NAME}_PKGCONFIG_TYPE ${${PACKAGE_NAME}_PKGCONFIG_TYPE}_PRIVATE)
else()
# Otherwise, use the plain type
set(PROJECT_${PACKAGE_NAME}_PKGCONFIG_TYPE ${${PACKAGE_NAME}_PKGCONFIG_TYPE})
endif()
# Append the entry as a string onto the project-wide variable for
# whichever requirement type we selected
ign_string_append(PROJECT_${PROJECT_${PACKAGE_NAME}_PKGCONFIG_TYPE} ${${PACKAGE_NAME}_PKGCONFIG_ENTRY})
endif()
if(ign_find_package_REQUIRED_BY)
# For each of the components that requires this package, append its
# entry as a string onto the component-specific variable for whichever
# requirement type we selected
foreach(component ${ign_find_package_REQUIRED_BY})
if(${component}_${PACKAGE_NAME}_PRIVATE)
# If this is a private library or module, use the _PRIVATE suffix
set(${component}_${PACKAGE_NAME}_PKGCONFIG_TYPE ${component}_${${PACKAGE_NAME}_PKGCONFIG_TYPE}_PRIVATE)
else()
# Otherwise, use the plain type
set(${component}_${PACKAGE_NAME}_PKGCONFIG_TYPE ${component}_${${PACKAGE_NAME}_PKGCONFIG_TYPE})
endif()
# Append the entry as a string onto the component-specific variable
# for whichever required type we selected
ign_string_append(${${component}_${PACKAGE_NAME}_PKGCONFIG_TYPE} ${${PACKAGE_NAME}_PKGCONFIG_ENTRY})
endforeach()
endif()
endif()
endif()
endif()
endmacro()
#################################################
# ign_string_append( [DELIM ])
#
# : The name of the string variable that should be appended to
#
# : The value that should be appended to the string
#
# [DELIM]: Specify a delimiter to separate the contents with. Default value is a
# space
#
# Macro to append a value to a string
macro(ign_string_append output_var val)
#------------------------------------
# Define the expected arguments
# NOTE: options cannot be set to PARENT_SCOPE alone, so we put it explicitly
# into cmake_parse_arguments(~). We use a semicolon to concatenate it with
# this options variable, so all other options should be specified here.
set(options)
set(oneValueArgs DELIM)
set(multiValueArgs) # We are not using multiValueArgs yet
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_string_append "PARENT_SCOPE;${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ign_string_append_DELIM)
set(delim "${ign_string_append_DELIM}")
else()
set(delim " ")
endif()
if( (NOT ${output_var}) OR (${output_var} STREQUAL "") )
# If ${output_var} is blank, just set it to equal ${val}
set(${output_var} "${val}")
else()
# If ${output_var} already has a value in it, append ${val} with the
# delimiter in-between.
set(${output_var} "${${output_var}}${delim}${val}")
endif()
if(ign_string_append_PARENT_SCOPE)
set(${output_var} "${${output_var}}" PARENT_SCOPE)
endif()
endmacro()
#################################################
# Macro to turn a list into a string
macro(ign_list_to_string _output _input_list)
set(${_output})
foreach(_item ${${_input_list}})
# Append each item, and forward any extra options to ign_string_append, such
# as DELIM or PARENT_SCOPE
ign_string_append(${_output} "${_item}" ${ARGN})
endforeach(_item)
endmacro()
#################################################
# ign_get_sources_and_unittests()
#
# Grab all the files ending in "*.cc" from either the "src/" subdirectory or the
# current subdirectory if "src/" does not exist. They will be collated into
# library source files and unittest source files .
#
# These output variables can be consumed directly by ign_create_core_library(~),
# ign_add_component(~), ign_build_tests(~), and ign_build_executables(~).
function(ign_get_libsources_and_unittests lib_sources_var tests_var)
# Glob all the source files
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/src)
# Prefer files in the src/ subdirectory
file(GLOB source_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "src/*.cc")
file(GLOB test_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "src/*_TEST.cc")
else()
# If src/ doesn't exist, then use the current directory
file(GLOB source_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "*.cc")
file(GLOB test_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "*_TEST.cc")
endif()
# Sort the files alphabetically
if(source_files)
list(SORT source_files)
endif()
if(test_files)
list(SORT test_files)
endif()
# Initialize the test list
set(tests)
# Remove the unit tests from the list of source files
foreach(test_file ${test_files})
# Remove from the source_files list.
list(REMOVE_ITEM source_files ${test_file})
# Append to the list of tests.
list(APPEND tests ${test_file})
endforeach()
# Return the lists that have been created.
set(${lib_sources_var} ${source_files} PARENT_SCOPE)
set(${tests_var} ${tests} PARENT_SCOPE)
endfunction()
#################################################
# ign_get_sources()
#
# From the current directory, grab all the source files and place them into
# . Remove their paths to make them suitable for passing into
# ign_add_[library/tests].
function(ign_get_sources sources_var)
# GLOB all the source files
file(GLOB source_files "*.cc")
list(SORT source_files)
# Initialize this list
set(sources)
foreach(source_file ${source_files})
# Remove the path from the source file and append it the list of soures
get_filename_component(source ${source_file} NAME)
list(APPEND sources ${source})
endforeach()
# Return the list that has been created
set(${sources_var} ${sources} PARENT_SCOPE)
endfunction()
#################################################
# ign_install_all_headers(
# [EXCLUDE_FILES ]
# [EXCLUDE_DIRS ]
# [GENERATED_HEADERS ]
# [COMPONENT] )
#
# From the current directory, install all header files, including files from all
# subdirectories (recursively). You can optionally specify directories or files
# to exclude from installation (the names must be provided relative to the current
# source directory).
#
# This will accept all files ending in *.h and *.hh. You may append an
# additional suffix (like .old or .backup) to prevent a file from being included.
#
# GENERATED_HEADERS should be generated headers which should be included by
# ${IGN_DESIGNATION}.hh. This will only add them to the header, it will not
# generate or install them.
#
# This will also run configure_file on ign_auto_headers.hh.in and config.hh.in
# and install them. This will NOT install any other files or directories that
# appear in the ${CMAKE_CURRENT_BINARY_DIR}.
#
# If the COMPONENT option is specified, this will skip over configuring a
# config.hh file since it would be redundant with the core library.
#
function(ign_install_all_headers)
#------------------------------------
# Define the expected arguments
set(options)
set(oneValueArgs COMPONENT) # We are not using oneValueArgs yet
set(multiValueArgs EXCLUDE_FILES EXCLUDE_DIRS GENERATED_HEADERS)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_install_all_headers "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#------------------------------------
# Build the list of directories
file(GLOB_RECURSE all_files LIST_DIRECTORIES TRUE RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*")
list(SORT all_files)
set(directories)
foreach(f ${all_files})
# Check if this file is a directory
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${f})
# Check if it is in the list of excluded directories
list(FIND ign_install_all_headers_EXCLUDE_DIRS ${f} f_index)
set(append_file TRUE)
foreach(subdir ${ign_install_all_headers_EXCLUDE_DIRS})
# Check if ${f} contains ${subdir} as a substring
string(FIND ${f} ${subdir} pos)
# If ${subdir} is a substring of ${f} at the very first position, then
# we should not include anything from this directory. This makes sure
# that if a user specifies "EXCLUDE_DIRS foo" we will also exclude
# the directories "foo/bar/..." and so on. We will not, however, exclude
# a directory named "bar/foo/".
if(${pos} EQUAL 0)
set(append_file FALSE)
break()
endif()
endforeach()
if(append_file)
list(APPEND directories ${f})
endif()
endif()
endforeach()
# Append the current directory to the list
list(APPEND directories ".")
#------------------------------------
# Install all the non-excluded header directories along with all of their
# non-excluded headers
foreach(dir ${directories})
# GLOB all the header files in dir
file(GLOB headers RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/*.h" "${dir}/*.hh" "${dir}/*.hpp")
list(SORT headers)
# Remove the excluded headers
if(headers)
foreach(exclude ${ign_install_all_headers_EXCLUDE_FILES})
list(REMOVE_ITEM headers ${exclude})
endforeach()
endif()
# Add each header, prefixed by its directory, to the auto headers variable
foreach(header ${headers})
set(ign_headers "${ign_headers}#include <${PROJECT_INCLUDE_DIR}/${header}>\n")
endforeach()
if("." STREQUAL ${dir})
set(destination "${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR}")
else()
set(destination "${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR}/${dir}")
endif()
install(
FILES ${headers}
DESTINATION ${destination}
COMPONENT headers)
endforeach()
# Add generated headers to the list of includes
foreach(header ${ign_install_all_headers_GENERATED_HEADERS})
set(ign_headers "${ign_headers}#include <${PROJECT_INCLUDE_DIR}/${header}>\n")
endforeach()
if(ign_install_all_headers_COMPONENT)
set(component_name ${ign_install_all_headers_COMPONENT})
# Define the install directory for the component meta header
set(meta_header_install_dir ${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR}/${component_name})
# Define the input/output of the configuration for the component "master" header
set(master_header_in ${IGNITION_CMAKE_DIR}/ign_auto_headers.hh.in)
set(master_header_out ${CMAKE_CURRENT_BINARY_DIR}/${component_name}.hh)
else()
# Define the install directory for the core master meta header
set(meta_header_install_dir ${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR})
# Define the input/output of the configuration for the core "master" header
set(master_header_in ${IGNITION_CMAKE_DIR}/ign_auto_headers.hh.in)
set(master_header_out ${CMAKE_CURRENT_BINARY_DIR}/../${IGN_DESIGNATION}.hh)
endif()
# Generate the "master" header that includes all of the headers
configure_file(${master_header_in} ${master_header_out})
# Install the "master" header
install(
FILES ${master_header_out}
DESTINATION ${meta_header_install_dir}/..
COMPONENT headers)
# Define the input/output of the configuration for the "config" header
set(config_header_in ${CMAKE_CURRENT_SOURCE_DIR}/config.hh.in)
set(config_header_out ${CMAKE_CURRENT_BINARY_DIR}/config.hh)
if(NOT ign_install_all_headers_COMPONENT)
# Produce an error if the config file is missing
#
# TODO: Maybe we should have a generic config.hh.in file that we fall back
# on if the project does not have one for itself?
if(NOT EXISTS ${config_header_in})
message(FATAL_ERROR
"Developer error: You are missing the file [${config_header_in}]! "
"Did you forget to move it from your project's cmake directory while "
"migrating to the use of ignition-cmake?")
endif()
# Generate the "config" header that describes our project configuration
configure_file(${config_header_in} ${config_header_out})
# Install the "config" header
install(
FILES ${config_header_out}
DESTINATION ${meta_header_install_dir}
COMPONENT headers)
endif()
endfunction()
#################################################
# ign_build_error macro
macro(ign_build_error)
foreach(str ${ARGN})
set(msg "\t${str}")
list(APPEND build_errors ${msg})
endforeach()
endmacro(ign_build_error)
#################################################
# ign_build_warning macro
macro(ign_build_warning)
foreach(str ${ARGN})
list(APPEND build_warnings "${str}")
endforeach(str ${ARGN})
endmacro(ign_build_warning)
#################################################
macro(ign_add_library lib_target_name)
message(FATAL_ERROR
"ign_add_library() is deprecated. Instead, use "
"ign_create_core_library(SOURCES ). It will determine the library "
"target name automatically from the project name. To add a component "
"library, use ign_add_component(~). Be sure to pass the CXX_STANDARD "
"argument to these functions in order to set the C++ standard that they "
"require.")
ign_create_core_library(SOURCES ${ARGN})
endmacro()
#################################################
# _ign_check_known_cxx_standards(<11|14|17>)
#
# Creates a fatal error if the variable passed in does not represent a supported
# version of the C++ standard.
#
# NOTE: This function is meant for internal ign-cmake use
#
function(_ign_check_known_cxx_standards standard)
list(FIND IGN_KNOWN_CXX_STANDARDS ${standard} known)
if(${known} EQUAL -1)
message(FATAL_ERROR
"You have specified an unsupported standard: ${standard}. "
"Accepted values are: ${IGN_KNOWN_CXX_STANDARDS}.")
endif()
endfunction()
#################################################
# _ign_handle_cxx_standard(
#
# )
#
# Handles the C++ standard argument for ign_create_core_library(~) and
# ign_add_component(~).
#
# NOTE: This is only meant for internal ign-cmake use.
#
macro(_ign_handle_cxx_standard prefix target pkgconfig_cflags)
if(${prefix}_CXX_STANDARD)
_ign_check_known_cxx_standards(${${prefix}_CXX_STANDARD})
endif()
if(${prefix}_PRIVATE_CXX_STANDARD)
_ign_check_known_cxx_standards(${${prefix}_PRIVATE_CXX_STANDARD})
endif()
if(${prefix}_INTERFACE_CXX_STANDARD)
_ign_check_known_cxx_standards(${${prefix}_INTERFACE_CXX_STANDARD})
endif()
if(${prefix}_CXX_STANDARD
AND (${prefix}_PRIVATE_CXX_STANDARD
OR ${prefix}_INTERFACE_CXX_STANDARD))
message(FATAL_ERROR
"If CXX_STANDARD has been specified, then you are not allowed to specify "
"PRIVATE_CXX_STANDARD or INTERFACE_CXX_STANDARD. Please choose to either "
"specify CXX_STANDARD alone, or else specify some combination of "
"PRIVATE_CXX_STANDARD and INTERFACE_CXX_STANDARD")
endif()
if(${prefix}_CXX_STANDARD)
set(${prefix}_INTERFACE_CXX_STANDARD ${${prefix}_CXX_STANDARD})
set(${prefix}_PRIVATE_CXX_STANDARD ${${prefix}_CXX_STANDARD})
endif()
if(${prefix}_INTERFACE_CXX_STANDARD)
target_compile_features(${target} INTERFACE ${IGN_CXX_${${prefix}_INTERFACE_CXX_STANDARD}_FEATURES})
ign_string_append(${pkgconfig_cflags} "-std=c++${${prefix}_INTERFACE_CXX_STANDARD}")
endif()
if(${prefix}_PRIVATE_CXX_STANDARD)
target_compile_features(${target} PRIVATE ${IGN_CXX_${${prefix}_PRIVATE_CXX_STANDARD}_FEATURES})
endif()
endmacro()
#################################################
# ign_create_core_library(SOURCES
# [CXX_STANDARD <11|14|17>]
# [PRIVATE_CXX_STANDARD <11|14|17>]
# [INTERFACE_CXX_STANDARD <11|14|17>]
# [GET_TARGET_NAME ]
# [LEGACY_PROJECT_PREFIX ])
#
# This function will produce the "core" library for your project. There is no
# need to specify a name for the library, because that will be determined by
# your project information.
#
# SOURCES: Required. Specify the source files that will be used to generate the
# library.
#
# [GET_TARGET_NAME]: Optional. The variable that follows this argument will be
# set to the library target name that gets produced by this
# function. The target name will always be
# ${PROJECT_LIBRARY_TARGET_NAME}.
#
# [LEGACY_PROJECT_PREFIX]: Optional. The variable that follows this argument will be
# used as a prefix for the legacy cmake config variables
# _LIBRARIES and _INCLUDE_DIRS.
#
# If you need a specific C++ standard, you must also specify it in this
# function in order to ensure that your library's target properties get set
# correctly. The following is a breakdown of your choices:
#
# [CXX_STANDARD]: This library must compile using the specified standard, and so
# must any libraries which link to it.
#
# [PRIVATE_CXX_STANDARD]: This library must compile using the specified standard,
# but libraries which link to it do not need to.
#
# [INTERFACE_CXX_STANDARD]: Any libraries which link to this library must compile
# with the specified standard.
#
# Most often, you will want to use CXX_STANDARD, but there may be cases in which
# you want a finer degree of control. If your library must compile with a
# different standard than what is required by dependent libraries, then you can
# specify both PRIVATE_CXX_STANDARD and INTERFACE_CXX_STANDARD without any
# conflict. However, both of those arguments conflict with CXX_STANDARD, so you
# are not allowed to use either of them if you use the CXX_STANDARD argument.
#
function(ign_create_core_library)
#------------------------------------
# Define the expected arguments
set(options INTERFACE)
set(oneValueArgs INCLUDE_SUBDIR LEGACY_PROJECT_PREFIX CXX_STANDARD PRIVATE_CXX_STANDARD INTERFACE_CXX_STANDARD GET_TARGET_NAME)
set(multiValueArgs SOURCES)
#------------------------------------
# Parse the arguments
cmake_parse_arguments(ign_create_core_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ign_create_core_library_SOURCES)
set(sources ${ign_create_core_library_SOURCES})
elseif(NOT ign_create_core_library_INTERFACE)
message(FATAL_ERROR "You must specify SOURCES for ign_create_core_library(~)!")
endif()
if(ign_create_core_library_INTERFACE)
set(interface_option INTERFACE)
set(property_type INTERFACE)
else()
set(interface_option) # Intentionally blank
set(property_type PUBLIC)
endif()
#------------------------------------
# Create the target for the core library, and configure it to be installed
_ign_add_library_or_component(
LIB_NAME ${PROJECT_LIBRARY_TARGET_NAME}
INCLUDE_DIR "${PROJECT_INCLUDE_DIR}"
EXPORT_BASE IGNITION_${IGN_DESIGNATION_UPPER}
SOURCES ${sources}
${interface_option})
# These generator expressions are necessary for multi-configuration generators
# such as MSVC on Windows. They also ensure that our target exports its
# headers correctly
target_include_directories(${PROJECT_LIBRARY_TARGET_NAME}
${property_type}
# This is the publicly installed headers directory.
"$"
# This is the in-build version of the core library headers directory.
# Generated headers for the core library get placed here.
"$"
# Generated headers for the core library might also get placed here.
"$")
# We explicitly create these directories to avoid false-flag compiler warnings
file(MAKE_DIRECTORY
"${PROJECT_BINARY_DIR}/include"
"${PROJECT_BINARY_DIR}/core/include")
if(EXISTS "${PROJECT_SOURCE_DIR}/include")
target_include_directories(${PROJECT_LIBRARY_TARGET_NAME}
${property_type}
# This is the build directory version of the headers. When exporting the
# target, this will not be included, because it is tied to the build
# interface instead of the install interface.
"$")
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/core/include")
target_include_directories(${PROJECT_LIBRARY_TARGET_NAME}
${property_type}
# This is the include directories for projects that put the core library
# contents into its own subdirectory.
"$")
endif()
#------------------------------------
# Adjust variables if a specific C++ standard was requested
_ign_handle_cxx_standard(ign_create_core_library
${PROJECT_LIBRARY_TARGET_NAME} PROJECT_PKGCONFIG_CFLAGS)
#------------------------------------
# Handle cmake and pkgconfig packaging
if(ign_create_core_library_INTERFACE)
set(project_pkgconfig_core_lib) # Intentionally blank
else()
set(project_pkgconfig_core_lib "-l${PROJECT_NAME_LOWER}")
endif()
# Export and install the core library's cmake target and package information
_ign_create_cmake_package(LEGACY_PROJECT_PREFIX ${ign_create_core_library_LEGACY_PROJECT_PREFIX})
# Generate and install the core library's pkgconfig information
_ign_create_pkgconfig()
#------------------------------------
# Pass back the target name if they ask for it.
if(ign_create_core_library_GET_TARGET_NAME)
set(${ign_create_core_library_GET_TARGET_NAME} ${PROJECT_LIBRARY_TARGET_NAME} PARENT_SCOPE)
endif()
endfunction()
#################################################
# ign_add_component(
# SOURCES | INTERFACE
# [DEPENDS_ON_COMPONENTS ]
# [INCLUDE_SUBDIR ]
# [GET_TARGET_NAME ]
# [INDEPENDENT_FROM_PROJECT_LIB]
# [PRIVATELY_DEPENDS_ON_PROJECT_LIB]
# [INTERFACE_DEPENDS_ON_PROJECT_LIB]
# [CXX_STANDARD <11|14|17>]
# [PRIVATE_CXX_STANDARD <11|14|17>]
# [INTERFACE_CXX_STANDARD <11|14|17>])
#
# This function will produce a "component" library for your project. This is the
# recommended way to produce plugins or library modules.
#
# : Required. Name of the component. The final name of this library
# and its target will be ignition--
#
# SOURCES: Required (unless INTERFACE is specified). Specify the source files
# that will be used to generate the library.
#
# INTERFACE: Indicate that this is an INTERFACE library which does not require
# any source files. This is required if SOURCES is not specified.
#
# [DEPENDS_ON_COMPONENTS]: Specify a list of other components of this package
# that this component depends on. This argument should
# be considered mandatory whenever there are
# inter-component dependencies in an ignition package.
#
# [INCLUDE_SUBDIR]: Optional. If specified, the public include headers for this
# component will go into "ignition///".
# If not specified, they will go into "ignition///"
#
# [GET_TARGET_NAME]: Optional. The variable that follows this argument will be
# set to the library target name that gets produced by this
# function. The target name will always be
# ${PROJECT_LIBRARY_TARGET_NAME}-.
#
# [INDEPENDENT_FROM_PROJECT_LIB]:
# Optional. Specify this if you do NOT want this component to automatically
# be linked to the core library of this project. The default behavior is to
# be publically linked.
#
# [PRIVATELY_DEPENDS_ON_PROJECT_LIB]:
# Optional. Specify this if this component privately depends on the core
# library of this project (i.e. users of this component do not need to
# interface with the core library). The default behavior is to be publicly
# linked.
#
# [INTERFACE_DEPENDS_ON_PROJECT_LIB]:
# Optional. Specify this if the component's interface depends on the core
# library of this project (i.e. users of this component need to interface
# with the core library), but the component itself does not need to link to
# the core library.
#
# See the documentation of ign_create_core_library(~) for more information about
# specifying the C++ standard. If your component publicly depends on the core
# library, then you probably do not need to specify the standard, because it
# will get inherited from the core library.
function(ign_add_component component_name)
#------------------------------------
# Define the expected arguments
set(options INTERFACE INDEPENDENT_FROM_PROJECT_LIB PRIVATELY_DEPENDS_ON_PROJECT_LIB INTERFACE_DEPENDS_ON_PROJECT_LIB)
set(oneValueArgs INCLUDE_SUBDIR GET_TARGET_NAME)
set(multiValueArgs SOURCES DEPENDS_ON_COMPONENTS)
#------------------------------------
# Parse the arguments
cmake_parse_arguments(ign_add_component "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(POLICY CMP0079)
cmake_policy(SET CMP0079 NEW)
endif()
if(ign_add_component_SOURCES)
set(sources ${ign_add_component_SOURCES})
elseif(NOT ign_add_component_INTERFACE)
message(FATAL_ERROR "You must specify SOURCES for ign_add_component(~)!")
endif()
if(ign_add_component_INCLUDE_SUBDIR)
set(include_subdir ${ign_add_component_INCLUDE_SUBDIR})
else()
set(include_subdir ${component_name})
endif()
if(ign_add_component_INTERFACE)
set(interface_option INTERFACE)
set(property_type INTERFACE)
else()
set(interface_option) # Intentionally blank
set(property_type PUBLIC)
endif()
# Set the name of the component's target
set(component_target_name ${PROJECT_LIBRARY_TARGET_NAME}-${component_name})
# Pass the component's target name back to the caller if requested
if(ign_add_component_GET_TARGET_NAME)
set(${ign_add_component_GET_TARGET_NAME} ${component_target_name} PARENT_SCOPE)
endif()
# Create an upper case version of the component name, to be used as an export
# base name.
string(TOUPPER ${component_name} component_name_upper)
# hyphen is not supported as macro name, replace it by underscore
string(REPLACE "-" "_" component_name_upper ${component_name_upper})
#------------------------------------
# Create the target for this component, and configure it to be installed
_ign_add_library_or_component(
LIB_NAME ${component_target_name}
INCLUDE_DIR "${PROJECT_INCLUDE_DIR}/${include_subdir}"
EXPORT_BASE IGNITION_${IGN_DESIGNATION_UPPER}_${component_name_upper}
SOURCES ${sources}
${interface_option})
if(ign_add_component_INDEPENDENT_FROM_PROJECT_LIB OR
ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB)
# If we are not linking this component to the core library, then we need to
# add these include directories to this component library directly. This is
# not needed if we link to the core library, because that will pull in these
# include directories automatically.
target_include_directories(${component_target_name}
${property_type}
# This is the publicly installed ignition/math headers directory.
"$"
# This is the in-build version of the core library's headers directory.
# Generated headers for this component might get placed here, even if
# the component is independent of the core library.
"$")
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/include")
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/${component_name}/include")
target_include_directories(${component_target_name}
${property_type}
# This is the in-source version of the component-specific headers
# directory. When exporting the target, this will not be included,
# because it is tied to the build interface instead of the install
# interface.
"$")
endif()
target_include_directories(${component_target_name}
${property_type}
# This is the in-build version of the component-specific headers
# directory. Generated headers for this component might end up here.
"$")
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/${component_name}/include")
#------------------------------------
# Adjust variables if a specific C++ standard was requested
_ign_handle_cxx_standard(ign_add_component
${component_target_name} ${component_name}_PKGCONFIG_CFLAGS)
#------------------------------------
# Adjust the packaging variables based on how this component depends (or not)
# on the core library.
if(ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB)
target_link_libraries(${component_target_name}
PRIVATE ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(ign_add_component_INTERFACE_DEPENDS_ON_PROJECT_LIB)
target_link_libraries(${component_target_name}
INTERFACE ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(NOT ign_add_component_INDEPENDENT_FROM_PROJECT_LIB AND
NOT ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB AND
NOT ign_add_component_INTERFACE_DEPENDS_ON_PROJECT_LIB)
target_link_libraries(${component_target_name}
${property_type} ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(NOT ign_add_component_INDEPENDENT_FROM_PROJECT_LIB)
# Add the core library as a cmake dependency for this component
# NOTE: It seems we need to triple-escape "${ign_package_required}" and
# "${ign_package_quiet}" here.
ign_string_append(${component_name}_CMAKE_DEPENDENCIES
"if(NOT ${PKG_NAME}_CONFIG_INCLUDED)\n find_package(${PKG_NAME} ${PROJECT_VERSION_FULL_NO_SUFFIX} EXACT \\\${ign_package_quiet} \\\${ign_package_required})\nendif()" DELIM "\n")
# Choose what type of pkgconfig entry the core library belongs to
set(lib_pkgconfig_type ${component_name}_PKGCONFIG_REQUIRES)
if(ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB
AND NOT ign_add_component_INTERFACE_DEPENDS_ON_PROJECT_LIB)
set(lib_pkgconfig_type ${lib_pkgconfig_type}_PRIVATE)
endif()
ign_string_append(${lib_pkgconfig_type} "${PKG_NAME} = ${PROJECT_VERSION_FULL_NO_SUFFIX}")
endif()
if(ign_add_component_DEPENDS_ON_COMPONENTS)
ign_string_append(${component_name}_CMAKE_DEPENDENCIES
"find_package(${PKG_NAME} ${PROJECT_VERSION_FULL_NO_SUFFIX} EXACT \\\${ign_package_quiet} \\\${ign_package_required} COMPONENTS ${ign_add_component_DEPENDS_ON_COMPONENTS})" DELIM "\n")
endif()
#------------------------------------
# Set variables that are needed by cmake/ignition-component-config.cmake.in
set(component_pkg_name ${component_target_name})
if(ign_add_component_INTERFACE)
set(component_pkgconfig_lib)
else()
set(component_pkgconfig_lib "-l${component_pkg_name}")
endif()
set(component_cmake_dependencies ${${component_name}_CMAKE_DEPENDENCIES})
# This next set is redundant, but it serves as a reminder that this input
# variable is used in config files
set(component_name ${component_name})
# ... and by cmake/pkgconfig/ignition-component.pc.in
set(component_pkgconfig_requires ${${component_name}_PKGCONFIG_REQUIRES})
set(component_pkgconfig_requires_private ${${component_name}_PKGCONFIG_REQUIRES_PRIVATE})
set(component_pkgconfig_lib_deps ${${component_name}_PKGCONFIG_LIBS})
set(component_pkgconfig_lib_deps_private ${${component_name}_PKGCONFIG_LIBS_PRIVATE})
set(component_pkgconfig_cflags ${${component_name}_PKGCONFIG_CFLAGS})
# Export and install the cmake target and package information
_ign_create_cmake_package(COMPONENT ${component_name})
# Generate and install the pkgconfig information for this component
_ign_create_pkgconfig(COMPONENT ${component_name})
#------------------------------------
# Add this component to the "all" target
target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME}-all INTERFACE ${lib_name})
get_property(all_known_components TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS)
if(NOT all_known_components)
set_property(TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS "${component_target_name}")
else()
set_property(TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS "${all_known_components};${component_target_name}")
endif()
endfunction()
#################################################
function(ign_create_all_target)
add_library(${PROJECT_LIBRARY_TARGET_NAME}-all INTERFACE)
install(
TARGETS ${PROJECT_LIBRARY_TARGET_NAME}-all
EXPORT ${PROJECT_LIBRARY_TARGET_NAME}-all
LIBRARY DESTINATION ${IGN_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${IGN_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${IGN_BIN_INSTALL_DIR}
COMPONENT libraries)
endfunction()
#################################################
function(ign_export_target_all)
# find_all_pkg_components is used as a variable in ignition-all-config.cmake.in
set(find_all_pkg_components "")
get_property(all_known_components TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS)
if(all_known_components)
foreach(component ${all_known_components})
ign_string_append(find_all_pkg_components "find_dependency(${component} ${PROJECT_VERSION_FULL_NO_SUFFIX} EXACT)" DELIM "\n")
endforeach()
endif()
_ign_create_cmake_package(ALL)
endfunction()
#################################################
# Used internally by _ign_add_library_or_component to report argument errors
macro(_ign_add_library_or_component_arg_error missing_arg)
message(FATAL_ERROR "ignition-cmake developer error: Must specify "
"${missing_arg} to _ign_add_library_or_component!")
endmacro()
#################################################
# This is only meant for internal use by ignition-cmake. If you are a consumer
# of ignition-cmake, please use ign_create_core_library(~) or
# ign_add_component(~) instead of this.
#
# _ign_add_library_or_component(LIB_NAME
# INCLUDE_DIR
# EXPORT_BASE
# SOURCES )
#
macro(_ign_add_library_or_component)
# NOTE: The following local variables are used in the Export.hh.in file, so if
# you change their names here, you must also change their names there:
# - include_dir
# - export_base
# - lib_name
#------------------------------------
# Define the expected arguments
set(options INTERFACE)
set(oneValueArgs LIB_NAME INCLUDE_DIR EXPORT_BASE)
set(multiValueArgs SOURCES)
#------------------------------------
# Parse the arguments
cmake_parse_arguments(_ign_add_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(_ign_add_library_LIB_NAME)
set(lib_name ${_ign_add_library_LIB_NAME})
else()
_ign_add_library_or_component_arg_error(LIB_NAME)
endif()
if(NOT _ign_add_library_INTERFACE)
if(_ign_add_library_SOURCES)
set(sources ${_ign_add_library_SOURCES})
else()
_ign_add_library_or_component_arg_error(SOURCES)
endif()
else()
set(sources)
endif()
if(_ign_add_library_INCLUDE_DIR)
set(include_dir ${_ign_add_library_INCLUDE_DIR})
else()
_ign_add_library_or_component_arg_error(INCLUDE_DIR)
endif()
if(_ign_add_library_EXPORT_BASE)
set(export_base ${_ign_add_library_EXPORT_BASE})
else()
_ign_add_library_or_component_arg_error(EXPORT_BASE)
endif()
# check that export_base has no invalid symbols
string(REPLACE "-" "_" export_base_replaced ${export_base})
if(NOT ${export_base} STREQUAL ${export_base_replaced})
message(FATAL_ERROR
"export_base has a hyphen which is not"
"supported by macros used for visibility")
endif()
#------------------------------------
# Create the library target
message(STATUS "Configuring library: ${lib_name}")
if(_ign_add_library_INTERFACE)
add_library(${lib_name} INTERFACE)
else()
add_library(${lib_name} ${sources})
endif()
#------------------------------------
# Add fPIC if we are supposed to
if(IGN_ADD_fPIC_TO_LIBRARIES AND NOT _ign_add_library_INTERFACE)
target_compile_options(${lib_name} PRIVATE -fPIC)
endif()
if(NOT _ign_add_library_INTERFACE)
#------------------------------------
# Generate export macro headers
# Note: INTERFACE libraries do not need the export header
set(binary_include_dir
"${CMAKE_BINARY_DIR}/include/${include_dir}")
set(implementation_file_name "${binary_include_dir}/detail/Export.hh")
include(GenerateExportHeader)
# This macro will generate a header called detail/Export.hh which implements
# some C-macros that are useful for exporting our libraries. The
# implementation header does not provide any commentary or explanation for its
# macros, so we tuck it away in the detail/ subdirectory, and then provide a
# public-facing header that provides commentary for the macros.
generate_export_header(${lib_name}
BASE_NAME ${export_base}
EXPORT_FILE_NAME ${implementation_file_name}
EXPORT_MACRO_NAME DETAIL_${export_base}_VISIBLE
NO_EXPORT_MACRO_NAME DETAIL_${export_base}_HIDDEN
DEPRECATED_MACRO_NAME IGN_DEPRECATED_ALL_VERSIONS)
set(install_include_dir
"${IGN_INCLUDE_INSTALL_DIR_FULL}/${include_dir}")
# Configure the installation of the automatically generated file.
install(
FILES "${implementation_file_name}"
DESTINATION "${install_include_dir}/detail"
COMPONENT headers)
# Configure the public-facing header for exporting and deprecating. This
# header provides commentary for the macros so that developers can know their
# purpose.
configure_file(
"${IGNITION_CMAKE_DIR}/Export.hh.in"
"${binary_include_dir}/Export.hh")
# Configure the installation of the public-facing header.
install(
FILES "${binary_include_dir}/Export.hh"
DESTINATION "${install_include_dir}"
COMPONENT headers)
set_target_properties(
${lib_name}
PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
VERSION ${PROJECT_VERSION_FULL})
endif()
#------------------------------------
# Configure the installation of the target
install(
TARGETS ${lib_name}
EXPORT ${lib_name}
LIBRARY DESTINATION ${IGN_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${IGN_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${IGN_BIN_INSTALL_DIR}
COMPONENT libraries)
endmacro()
#################################################
macro(ign_add_executable _name)
add_executable(${_name} ${ARGN})
target_link_libraries(${_name} ${general_libraries})
endmacro()
#################################################
# ign_target_interface_include_directories( [include_targets])
#
# Add the INTERFACE_INCLUDE_DIRECTORIES of [include_targets] to the public
# INCLUDE_DIRECTORIES of . This allows us to propagate the include
# directories of along to any other libraries that depend on it.
#
# You MUST pass in targets to include, not directory names. We must not use
# explicit directory names here if we want our package to be relocatable.
function(ign_target_interface_include_directories name)
foreach(include_target ${ARGN})
target_include_directories(
${name} PUBLIC
$)
endforeach()
endfunction()
#################################################
macro(ign_install_includes _subdir)
install(FILES ${ARGN}
DESTINATION ${IGN_INCLUDE_INSTALL_DIR}/${_subdir} COMPONENT headers)
endmacro()
#################################################
macro(ign_install_library)
message(FATAL_ERROR
"ign_install_library is deprecated. "
"Please remove it from your cmake script!")
endmacro()
#################################################
macro(ign_install_executable _name )
set_target_properties(${_name} PROPERTIES VERSION ${PROJECT_VERSION_FULL})
install (TARGETS ${_name} DESTINATION ${IGN_BIN_INSTALL_DIR})
manpage(${_name} 1)
endmacro()
#################################################
# Macro to setup supported compiler warnings
# Based on work of Florent Lamiraux, Thomas Moulard, JRL, CNRS/AIST.
macro(ign_filter_valid_compiler_options var)
include(CheckCXXCompilerFlag)
# Store the current setting for CMAKE_REQUIRED_QUIET
set(original_cmake_required_quiet ${CMAKE_REQUIRED_QUIET})
# Make these tests quiet so they don't pollute the cmake output
set(CMAKE_REQUIRED_QUIET true)
foreach(flag ${ARGN})
CHECK_CXX_COMPILER_FLAG(${flag} result${flag})
if(result${flag})
set(${var} "${${var}} ${flag}")
endif()
endforeach()
# Restore the old setting for CMAKE_REQUIRED_QUIET
set(CMAKE_REQUIRED_QUIET ${original_cmake_required_quiet})
endmacro()
#################################################
# ign_build_executables(SOURCES
# [PREFIX ]
# [LIB_DEPS ]
# [INCLUDE_DIRS ]
# [EXEC_LIST ]
# [EXCLUDE_PROJECT_LIB])
#
# Build executables for an ignition project. Arguments are as follows:
#
# SOURCES: Required. The names (without a path) of the source files for your
# executables.
#
# PREFIX: Optional. This will append onto each executable name.
#
# LIB_DEPS: Optional. Additional library dependencies that every executable
# should link to, not including the library build by this project (it
# will be linked automatically, unless you pass in the
# EXCLUDE_PROJECT_LIB option).
#
# INCLUDE_DIRS: Optional. Additional include directories that should be visible
# to all of these executables.
#
# EXEC_LIST: Optional. Provide a variable which will be given the list of the
# names of the executables generated by this macro. These will also
# be the names of the targets.
#
# EXCLUDE_PROJECT_LIB: Pass this argument if you do not want your executables to
# link to your project's core library. On Windows, this
# will also skip the step of copying the runtime library
# into your executable's directory.
#
macro(ign_build_executables)
#------------------------------------
# Define the expected arguments
set(options EXCLUDE_PROJECT_LIB)
set(oneValueArgs PREFIX EXEC_LIST)
set(multiValueArgs SOURCES LIB_DEPS INCLUDE_DIRS)
if(ign_build_executables_EXEC_LIST)
set(${ign_build_executables_EXEC_LIST} "")
endif()
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_build_executables "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
foreach(exec_file ${ign_build_executables_SOURCES})
get_filename_component(BINARY_NAME ${exec_file} NAME_WE)
set(BINARY_NAME ${ign_build_executables_PREFIX}${BINARY_NAME})
add_executable(${BINARY_NAME} ${exec_file})
if(ign_build_executables_EXEC_LIST)
list(APPEND ${ign_build_executables_EXEC_LIST} ${BINARY_NAME})
endif()
if(NOT ign_build_executables_EXCLUDE_PROJECT_LIB)
target_link_libraries(${BINARY_NAME} ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(ign_build_executables_LIB_DEPS)
target_link_libraries(${BINARY_NAME} ${ign_build_executables_LIB_DEPS})
endif()
target_include_directories(${BINARY_NAME}
PRIVATE
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
${ign_build_executables_INCLUDE_DIRS})
endforeach()
endmacro()
#################################################
# ign_build_tests(TYPE
# SOURCES
# [LIB_DEPS ]
# [INCLUDE_DIRS ]
# [TEST_LIST ])
#
# Build tests for an ignition project. Arguments are as follows:
#
# TYPE: Required. Preferably UNIT, INTEGRATION, PERFORMANCE, or REGRESSION.
#
# SOURCES: Required. The names (without the path) of the source files for your
# tests. Each file will turn into a test.
#
# LIB_DEPS: Optional. Additional library dependencies that every test should
# link to, not including the library built by this project (it will be
# linked automatically). gtest and gtest_main will also be linked.
#
# INCLUDE_DIRS: Optional. Additional include directories that should be visible
# to all the tests of this type.
#
# TEST_LIST: Optional. Provide a variable which will be given the list of the
# names of the tests generated by this macro. These will also be the
# names of the targets.
#
# EXCLUDE_PROJECT_LIB: Pass this argument if you do not want your tests to
# link to your project's core library. On Windows, this
# will also skip the step of copying the runtime library
# into your executable's directory.
#
macro(ign_build_tests)
#------------------------------------
# Define the expected arguments
set(options SOURCE EXCLUDE_PROJECT_LIB) # NOTE: DO NOT USE "SOURCE", we're adding it here to catch typos
set(oneValueArgs TYPE TEST_LIST)
set(multiValueArgs SOURCES LIB_DEPS INCLUDE_DIRS)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_build_tests "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT ign_build_tests_TYPE)
# If you have encountered this error, you are probably migrating to the
# new ignition-cmake system. Be sure to also provide a SOURCES argument
# when calling ign_build_tests.
message(FATAL_ERROR "Developer error: You must specify a TYPE for your tests!")
endif()
if(ign_build_tests_SOURCE)
# We have encountered cases where someone accidentally passes a SOURCE
# argument instead of a SOURCES argument into ign_build_tests, and the macro
# didn't report any problem with it. Adding this warning should make it more
# clear when that particular typo occurs.
message(AUTHOR_WARNING
"Your script has specified SOURCE for ign_build_tests, which is not an "
"option. Did you mean to specify SOURCES (note the plural)?")
endif()
set(TEST_TYPE ${ign_build_tests_TYPE})
if(BUILD_TESTING)
if(NOT DEFINED ign_build_tests_SOURCES)
message(STATUS "No tests have been specified for ${TEST_TYPE}")
else()
list(LENGTH ign_build_tests_SOURCES num_tests)
message(STATUS "Adding ${num_tests} ${TEST_TYPE} tests")
endif()
if(NOT ign_build_tests_EXCLUDE_PROJECT_LIB)
ign_build_executables(
PREFIX "${TEST_TYPE}_"
SOURCES ${ign_build_tests_SOURCES}
LIB_DEPS gtest gtest_main ${ign_build_tests_LIB_DEPS}
INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/test/gtest/include ${ign_build_tests_INCLUDE_DIRS}
EXEC_LIST test_list)
else()
ign_build_executables(
PREFIX "${TEST_TYPE}_"
SOURCES ${ign_build_tests_SOURCES}
LIB_DEPS gtest gtest_main ${ign_build_tests_LIB_DEPS}
INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/test/gtest/include ${ign_build_tests_INCLUDE_DIRS}
EXEC_LIST test_list
EXCLUDE_PROJECT_LIB)
endif()
if(ign_build_tests_TEST_LIST)
set(${ign_build_tests_TEST_LIST} ${test_list})
endif()
# Find the Python interpreter for running the
# check_test_ran.py script
include(IgnPython)
# Build all the tests
foreach(target_name ${test_list})
if(USE_LOW_MEMORY_TESTS)
target_compile_options(${target_name} PRIVATE -DUSE_LOW_MEMORY_TESTS=1)
endif()
add_test(NAME ${target_name} COMMAND
${target_name} --gtest_output=xml:${CMAKE_BINARY_DIR}/test_results/${target_name}.xml)
if(UNIX)
# gtest requies pthread when compiled on a Unix machine
target_link_libraries(${target_name} pthread)
endif()
set_tests_properties(${target_name} PROPERTIES TIMEOUT 240)
if(PYTHONINTERP_FOUND)
# Check that the test produced a result and create a failure if it didn't.
# Guards against crashed and timed out tests.
add_test(check_${target_name} ${PYTHON_EXECUTABLE} ${IGNITION_CMAKE_TOOLS_DIR}/check_test_ran.py
${CMAKE_BINARY_DIR}/test_results/${target_name}.xml)
endif()
endforeach()
else()
message(STATUS "Testing is disabled -- skipping ${TEST_TYPE} tests")
endif()
endmacro()
#################################################
# ign_set_target_public_cxx_standard(<11|14|17>)
#
# NOTE: This was a temporary workaround for an earlier prerelease and is
# deprecated as of the "Components" pull request.
#
macro(ign_set_project_public_cxx_standard standard)
message(FATAL_ERROR
"The ign_set_project_public_cxx_standard(~) macro is deprecated. "
"Instead, use the CXX_STANDARD argument of ign_create_core_library(~).")
_ign_check_known_cxx_standards(${standard})
target_compile_features(${PROJECT_LIBRARY_TARGET_NAME} PUBLIC ${IGN_CXX_${standard}_FEATURES})
# Note: We have to reconfigure the pkg-config information for the core library
# because this macro can only be called after ign_create_core_library(~). This
# is somewhat wasteful, so we should strongly prefer to use the CXX_STANDARD
# argument of ign_create_core_library(~).
ign_string_append(PROJECT_PKGCONFIG_CFLAGS "-std=c++${standard}")
_ign_create_pkgconfig()
endmacro()
#################################################
# _ign_cmake_parse_arguments( [ARGN])
#
# Set to match the prefix that is given to cmake_parse_arguments(~).
# This should also match the name of the function or macro that called it.
#
# NOTE: This should only be used by functions inside of ign-cmake specifically.
# Other ignition projects should not use this macro.
#
macro(_ign_cmake_parse_arguments prefix options oneValueArgs multiValueArgs)
cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(${prefix}_UNPARSED_ARGUMENTS)
# The user passed in some arguments that we don't currently recognize. We'll
# emit a warning so they can check whether they're using the correct version
# of ign-cmake.
message(AUTHOR_WARNING
"\nThe build script has specified some unrecognized arguments for ${prefix}(~):\n"
"${${prefix}_UNPARSED_ARGUMENTS}\n"
"Either the script has a typo, or it is using an unexpected version of ign-cmake. "
"The version of ign-cmake currently being used is ${ignition-cmake${IGNITION_CMAKE_VERSION_MAJOR}_VERSION}\n")
endif()
endmacro()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnGenerateVersionInfo.cmake 0000664 0001750 0001750 00000005457 14160533245 025063 0 ustar jrivero jrivero #.rst
# IgnGenerateVersionInfo
# ----------------------
#
# Intended to be invoked as part of the ign_add_version_info_target function
# in IgnBenchmark.
#
# Populates information in the version_info.json file.
#
#===============================================================================
# Copyright (C) 2019 Open Source Robotics Foundation
#
# Licensed 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.
# Retrieve information about the mercurial state.
execute_process(
COMMAND hg id --id
WORKING_DIRECTORY ${repository_root}
OUTPUT_VARIABLE HG_GLOBAL_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND hg id --num
WORKING_DIRECTORY ${repository_root}
OUTPUT_VARIABLE HG_REVISION_NUM
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND hg id --branch
WORKING_DIRECTORY ${repository_root}
OUTPUT_VARIABLE HG_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Set time that this build occurred.
# Adding a dependency to this target will cause this file to be generated
# with each build, updating the timestamp accordingly.
string(TIMESTAMP build_time UTC)
# Retrieve information about the host system
# Ref: https://cmake.org/cmake/help/latest/command/cmake_host_system_information.html
cmake_host_system_information(RESULT NUM_LOGICAL QUERY NUMBER_OF_LOGICAL_CORES)
cmake_host_system_information(RESULT NUM_PHYSICAL QUERY NUMBER_OF_PHYSICAL_CORES)
cmake_host_system_information(RESULT HOST QUERY HOSTNAME)
cmake_host_system_information(RESULT FQDN QUERY FQDN)
cmake_host_system_information(RESULT TOTAL_VIRTUAL QUERY TOTAL_VIRTUAL_MEMORY)
cmake_host_system_information(RESULT AVAILABLE_VIRTUAL QUERY AVAILABLE_VIRTUAL_MEMORY)
cmake_host_system_information(RESULT TOTAL_PHYSICAL QUERY TOTAL_PHYSICAL_MEMORY)
cmake_host_system_information(RESULT AVAILABLE_PHYSICAL QUERY AVAILABLE_PHYSICAL_MEMORY)
cmake_host_system_information(RESULT PROC_NAME QUERY PROCESSOR_NAME)
cmake_host_system_information(RESULT PROC_DESC QUERY PROCESSOR_DESCRIPTION)
cmake_host_system_information(RESULT PROC_SERIAL QUERY PROCESSOR_SERIAL_NUMBER)
cmake_host_system_information(RESULT OS_NAME QUERY OS_NAME)
cmake_host_system_information(RESULT OS_RELEASE QUERY OS_RELEASE)
cmake_host_system_information(RESULT OS_VERSION QUERY OS_VERSION)
cmake_host_system_information(RESULT OS_PLATFORM QUERY OS_PLATFORM)
configure_file(${input_file} ${output_file})
ign-cmake-ignition-cmake2_2.10.0/cmake/Export.hh.in 0000664 0001750 0001750 00000004536 14160533245 021713 0 ustar jrivero jrivero /*
* Copyright (C) 2017 Open Source Robotics Foundation
*
* Licensed 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.
*
*/
/*
* ==========================================================================
* This file was automatically generated by CMake; do not modify it directly.
* To modify this file, make changes to ign-cmake/cmake/Export.hh.in
* ==========================================================================
*/
#ifndef @export_base@_EXPORT_HH_
#define @export_base@_EXPORT_HH_
// The detail/Export.hh header is automatically generated by CMake, which only
// provides the system-dependent implementations of these macros, with no
// commentary or explanation, so we configure this public-facing header which
// leverages the auto-generated macros but provides commentary for them.
#include "@include_dir@/detail/Export.hh"
#ifndef @export_base@_VISIBLE
/// For @lib_name@ developers: Apply this macro to @lib_name@
/// functions and classes which consumers of this library will need to be able
/// to call from their own programs or libraries.
#define @export_base@_VISIBLE \
DETAIL_@export_base@_VISIBLE
#endif
#ifndef @export_base@_HIDDEN
/// For @lib_name@ developers: Apply this macro to @lib_name@
/// functions and classes which must not be used by consumers of this library.
/// By default, this property is applied to all classes and functions which are
/// not tagged with @export_base@_VISIBLE, so this does not
/// generally need to be used.
#define @export_base@_HIDDEN \
DETAIL_@export_base@_HIDDEN
#endif
#ifndef IGN_DEPRECATED
/// For @lib_name@ developers: Use this macro to indicate that a
/// function or class has been deprecated and should no longer be used. A
/// version should be specified to provide context to the user about when the
/// function became deprecated.
#define IGN_DEPRECATED(version) IGN_DEPRECATED_ALL_VERSIONS
#endif
#endif
ign-cmake-ignition-cmake2_2.10.0/cmake/FindJSONCPP.cmake 0000664 0001750 0001750 00000004757 14160533245 022430 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 jsoncpp.
#
# Usage of this module as follows:
#
# find_package(JSONCPP)
#
# Variables defined by this module:
#
# JSONCPP_FOUND System has JSONCPP libs/headers
# JSONCPP_INCLUDE_DIRS The location of JSONCPP headers
# JSONCPP_LIBRARIES The JSONCPP libraries
# JSONCPP_TARGET Imported target for libjsoncpp
if(JSONCPP_FIND_VERSION)
message(WARNING "FindJSONCPP doesn't support the request of specific "
"versions. Please do not use VERSION.")
else()
find_package(jsoncpp CONFIG QUIET)
set(JSONCPP_TARGET jsoncpp_lib)
include(IgnPkgConfig)
if(JSONCPP_FOUND)
ign_pkg_config_entry(JSONCPP jsoncpp)
else()
ign_pkg_check_modules_quiet(JSONCPP jsoncpp)
set(JSONCPP_TARGET JSONCPP::JSONCPP)
# If that failed, then fall back to manual detection.
if(NOT JSONCPP_FOUND)
if(NOT JSONCPP_FIND_QUIETLY)
message(STATUS "Attempting manual search for jsoncpp")
endif()
find_path(JSONCPP_INCLUDE_DIRS json/json.h ${JSONCPP_INCLUDE_DIRS} ENV CPATH)
find_library(JSONCPP_LIBRARIES NAMES jsoncpp)
set(JSONCPP_FOUND true)
if(NOT JSONCPP_INCLUDE_DIRS)
if(NOT JSONCPP_FIND_QUIETLY)
message(STATUS "Looking for jsoncpp headers - not found")
endif()
set(JSONCPP_FOUND false)
endif()
if(NOT JSONCPP_LIBRARIES)
if(NOT JSONCPP_FIND_QUIETLY)
message (STATUS "Looking for jsoncpp library - not found")
endif()
set(JSONCPP_FOUND false)
endif()
if(JSONCPP_FOUND)
include(IgnImportTarget)
ign_import_target(JSONCPP)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
JSONCPP
REQUIRED_VARS JSONCPP_FOUND)
endif()
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindDL.cmake 0000664 0001750 0001750 00000005405 14160533245 021602 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 libdl
if(MSVC)
# The dlfcn-win32 library installs a config module, so we should leverage that
find_package(dlfcn-win32)
# Note: Ideally, we would create an alias target for dlfcn-win32::dl, but
# cmake does not (currently) support aliasing imported targets
# (see: https://gitlab.kitware.com/cmake/cmake/issues/15569)
#
# For now, we will use a variable named DL_TARGET for linking, even though
# it is old-fashioned. If a day comes when cmake supported aliasing
# imported targets, then we should migrate to something like
#
# add_library(DL::DL ALIAS dlfcn-win32::dl)
#
# And then link to DL::DL.
set(DL_TARGET dlfcn-win32::dl)
if(dlfcn-win32_FOUND)
set(DL_FOUND true)
else()
set(DL_FOUND false)
endif()
else()
# NOTE: libdl is a system library on UNIX, so it does not come with pkgconfig metadata
# If we cannot find the header or the library, we will switch this to false
set(DL_FOUND true)
# Search for the header
find_path(DL_INCLUDE_DIRS dlfcn.h)
if(DL_INCLUDE_DIRS)
if(NOT DL_FIND_QUIETLY)
message(STATUS "Looking for dlfcn.h - found")
endif()
else(DL_INCLUDE_DIRS)
if(NOT DL_FIND_QUIETLY)
message(STATUS "Looking for dlfcn.h - not found")
endif()
set(DL_FOUND false)
endif()
mark_as_advanced(DL_INCLUDE_DIRS)
# Search for the library
find_library(DL_LIBRARIES dl)
if(DL_LIBRARIES)
if(NOT DL_FIND_QUIETLY)
message(STATUS "Looking for libdl - found")
endif()
else(DL_LIBRARIES)
if(NOT DL_FIND_QUIETLY)
message(STATUS "Looking for libdl - not found")
endif()
set(DL_FOUND false)
endif()
mark_as_advanced(DL_LIBRARIES)
if(DL_FOUND)
include(IgnImportTarget)
ign_import_target(DL)
set(DL_TARGET DL::DL)
endif()
endif()
# We need to manually specify the pkgconfig entry (and type of entry) for dl,
# because ign_pkg_check_modules does not work for it.
include(IgnPkgConfig)
ign_pkg_config_library_entry(DL dl)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
DL
REQUIRED_VARS DL_FOUND)
ign-cmake-ignition-cmake2_2.10.0/cmake/FindYAML.cmake 0000664 0001750 0001750 00000005557 14160533245 022055 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 yaml.
#
# Usage of this module as follows:
#
# find_package(YAML)
#
# Variables defined by this module:
#
# YAML_TARGET Imported target for libyaml
#
# YAML_FOUND System has YAML libs/headers
# YAML_INCLUDE_DIRS The location of YAML headers
# YAML_LIBRARIES The YAML libraries
# initialize this variable to the default target name
set(YAML_TARGET YAML::YAML)
find_package(yaml ${YAML_FIND_VERSION} CONFIG QUIET)
if (yaml_FOUND)
# yaml's cmake script imports its own target, so we'll
# overwrite the default with the name of theirs. In the
# future, we should be able to use a target alias instead.
set(YAML_TARGET yaml)
set(YAML_FOUND True)
set(YAML_INCLUDE_DIRS ${yaml_INCLUDE_DIRS})
set(YAML_LIBRARIES ${yaml_LIBRARIES})
return()
endif()
if(YAML_FIND_VERSION AND NOT YAML_FIND_VERSION VERSION_EQUAL "0.1")
message(WARNING "FindYAML only knows how to find version 0.1 "
"but you requested version ${YAML_FIND_VERSION}.")
else()
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(YAML yaml-0.1)
# If that failed, then fall back to manual detection.
if(NOT YAML_FOUND)
if(NOT YAML_FIND_QUIETLY)
message(STATUS "Attempting manual search for yaml")
endif()
find_path(YAML_INCLUDE_DIRS yaml.h ${YAML_INCLUDE_DIRS} ENV CPATH)
find_library(YAML_LIBRARIES NAMES yaml)
set(YAML_FOUND true)
if(NOT YAML_INCLUDE_DIRS)
if(NOT YAML_FIND_QUIETLY)
message(STATUS "Looking for yaml headers - not found")
endif()
set(YAML_FOUND false)
endif()
if(NOT YAML_LIBRARIES)
if(NOT YAML_FIND_QUIETLY)
message (STATUS "Looking for yaml library - not found")
endif()
set(YAML_FOUND false)
endif()
if(YAML_FOUND)
include(IgnImportTarget)
ign_import_target(YAML)
message(STATUS "Assuming libyaml is static, defining YAML_DECLARE_STATIC")
set_target_properties(YAML::YAML PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "YAML_DECLARE_STATIC"
)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
YAML
REQUIRED_VARS YAML_FOUND)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindIgnOGRE.cmake 0000664 0001750 0001750 00000024706 14160533245 022502 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2018 Open Source Robotics Foundation
#
# Licensed 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 OGRE headers and libraries
#
# Usage of this module as follows:
#
# ign_find_package(IgnOGRE)
#
# Variables defined by this module:
#
# OGRE_FOUND System has OGRE libs/headers
# OGRE_LIBRARIES The OGRE libraries
# OGRE_INCLUDE_DIRS The location of OGRE headers
# OGRE_VERSION Full OGRE version in the form of MAJOR.MINOR.PATCH
# OGRE_VERSION_MAJOR OGRE major version
# OGRE_VERSION_MINOR OGRE minor version
# OGRE_VERSION_PATCH OGRE patch version
# OGRE_RESOURCE_PATH Path to ogre plugins directory
# IgnOGRE::IgnOGRE Imported target for OGRE
#
# On Windows, we assume that all the OGRE* defines are passed in manually
# to CMake.
#
# Supports finding the following OGRE components: RTShaderSystem, Terrain, Overlay
#
# Example usage:
#
# ign_find_package(IgnOGRE
# VERSION 1.8.0
# COMPONENTS RTShaderSystem Terrain Overlay)
# Grab the version numbers requested by the call to find_package(~)
set(major_version ${IgnOGRE_FIND_VERSION_MAJOR})
set(minor_version ${IgnOGRE_FIND_VERSION_MINOR})
# Set the full version number
set(full_version ${major_version}.${minor_version})
# Copied from OGREConfig.cmake
macro(ign_ogre_declare_plugin TYPE COMPONENT)
set(OGRE_${TYPE}_${COMPONENT}_FOUND TRUE)
set(OGRE_${TYPE}_${COMPONENT}_LIBRARIES ${TYPE}_${COMPONENT})
list(APPEND OGRE_LIBRARIES ${TYPE}_${COMPONENT})
endmacro()
if (NOT WIN32)
# pkg-config platforms
set(PKG_CONFIG_PATH_ORIGINAL $ENV{PKG_CONFIG_PATH})
set(PKG_CONFIG_PATH_TMP ${PKG_CONFIG_PATH_ORIGINAL})
execute_process(COMMAND pkg-config --variable pc_path pkg-config
OUTPUT_VARIABLE _pkgconfig_invoke_result
RESULT_VARIABLE _pkgconfig_failed)
if(_pkgconfig_failed)
IGN_BUILD_WARNING ("Failed to get pkg-config search paths")
elseif (NOT _pkgconfig_invoke_result STREQUAL "")
set (PKG_CONFIG_PATH_TMP "${PKG_CONFIG_PATH_TMP}:${_pkgconfig_invoke_result}")
endif()
# check and see if there are any paths at all
if ("${PKG_CONFIG_PATH_TMP}" STREQUAL "")
message("No valid pkg-config search paths found")
return()
endif()
string(REPLACE ":" ";" PKG_CONFIG_PATH_TMP ${PKG_CONFIG_PATH_TMP})
# loop through pkg config paths and find an ogre version that is < 2.0.0
foreach(pkg_path ${PKG_CONFIG_PATH_TMP})
if (NOT EXISTS ${pkg_path})
continue()
endif()
set(OGRE_FOUND false)
set(OGRE_INCLUDE_DIRS "")
set(OGRE_LIBRARY_DIRS "")
set(OGRE_LIBRARIES "")
set(ENV{PKG_CONFIG_PATH} ${pkg_path})
ign_pkg_check_modules_quiet(OGRE "OGRE >= ${full_version}"
NO_CMAKE_ENVIRONMENT_PATH
QUIET)
if (OGRE_FOUND)
if (NOT ${OGRE_VERSION} VERSION_LESS 2.0.0)
set (OGRE_FOUND false)
else ()
# set library dirs if the value is empty
if (NOT ${OGRE_LIBRARY_DIRS} OR ${OGRE_LIBRARY_DIRS} STREQUAL "")
execute_process(COMMAND pkg-config --variable=libdir OGRE
OUTPUT_VARIABLE _pkgconfig_invoke_result
RESULT_VARIABLE _pkgconfig_failed)
if(_pkgconfig_failed)
IGN_BUILD_WARNING ("Failed to find OGRE's library directory. The build will succeed, but there will likely be run-time errors.")
else()
# set ogre library dir and strip line break
set(OGRE_LIBRARY_DIRS ${_pkgconfig_invoke_result})
string(REGEX REPLACE "\n$" "" OGRE_LIBRARY_DIRS "${OGRE_LIBRARY_DIRS}")
string(FIND "${OGRE_LIBRARIES}" "${OGRE_LIBRARY_DIRS}" substr_found)
# in some cases the value of OGRE_LIBRARIES is "OgreMain;pthread"
# Convert this to full path to library
if (substr_found EQUAL -1)
foreach(OGRE_LIBRARY_NAME ${OGRE_LIBRARIES})
find_library(OGRE_LIBRARY NAMES ${OGRE_LIBRARY_NAME}
HINTS ${OGRE_LIBRARY_DIRS} NO_DEFAULT_PATH)
list (APPEND TMP_OGRE_LIBRARIES "${OGRE_LIBRARY}")
endforeach()
set(OGRE_LIBRARIES ${TMP_OGRE_LIBRARIES})
endif()
endif()
endif()
break()
endif()
endif()
endforeach()
if (OGRE_FOUND)
# set OGRE major, minor, and patch version number
string (REGEX REPLACE "^([0-9]+).*" "\\1"
OGRE_VERSION_MAJOR "${OGRE_VERSION}")
string (REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1"
OGRE_VERSION_MINOR "${OGRE_VERSION}")
string (REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1"
OGRE_VERSION_PATCH ${OGRE_VERSION})
# find ogre components
foreach(component ${IgnOGRE_FIND_COMPONENTS})
ign_pkg_check_modules_quiet(IgnOGRE-${component} "OGRE-${component} >= ${full_version}" NO_CMAKE_ENVIRONMENT_PATH)
if(IgnOGRE-${component}_FOUND)
list(APPEND OGRE_LIBRARIES IgnOGRE-${component}::IgnOGRE-${component})
elseif(IgnOGRE_FIND_REQUIRED_${component})
set(OGRE_FOUND false)
endif()
endforeach()
execute_process(COMMAND pkg-config --variable=plugindir OGRE
OUTPUT_VARIABLE _pkgconfig_invoke_result
RESULT_VARIABLE _pkgconfig_failed)
if(_pkgconfig_failed)
IGN_BUILD_WARNING ("Failed to find OGRE's plugin directory. The build will succeed, but there will likely be run-time errors.")
else()
# This variable will be substituted into cmake/setup.sh.in
set(OGRE_PLUGINDIR ${_pkgconfig_invoke_result})
endif()
ign_pkg_config_library_entry(IgnOGRE OgreMain)
set(OGRE_RESOURCE_PATH ${OGRE_PLUGINDIR})
# Seems that OGRE_PLUGINDIR can end in a newline, which will cause problems
# when we pass it to the compiler later.
string(REPLACE "\n" "" OGRE_RESOURCE_PATH ${OGRE_RESOURCE_PATH})
endif()
#reset pkg config path
set(ENV{PKG_CONFIG_PATH} ${PKG_CONFIG_PATH_ORIGINAL})
else()
find_package(OGRE ${full_version}
COMPONENTS ${IgnOGRE_FIND_COMPONENTS})
if(OGRE_FOUND)
# OGREConfig.cmake from vcpkg disable the link against plugin libs
# when compiling the shared version of it. Here we copied the code
# to use it.
foreach(ogre_component ${IgnOGRE_FIND_COMPONENTS})
if(ogre_component MATCHES "Plugin_" OR ogre_component MATCHES "RenderSystem_")
string(LENGTH "${ogre_component}" len)
string(FIND "${ogre_component}" "_" split_pos)
math(EXPR split_pos2 "${split_pos}+1")
string(SUBSTRING "${ogre_component}" "0" "${split_pos}" component_type)
string(SUBSTRING "${ogre_component}" "${split_pos2}" "${len}" component_name)
ign_ogre_declare_plugin("${component_type}" "${component_name}")
endif()
endforeach()
# need to return only libraries defined by components and give them the
# full path using OGRE_LIBRARY_DIRS
# Note: the OGREConfig.cmake installed by vcpkg generates variables that
# contain unwanted substrings so the string regex replace is added to
# fix the ogre dir path and lib vars.
# TODO(anyone) check if this is an OGRE vcpkg config issue.
string(REGEX REPLACE "\\$.*>" "" OGRE_LIBRARY_DIRS ${OGRE_LIBRARY_DIRS})
set(ogre_all_libs)
foreach(ogre_lib ${OGRE_LIBRARIES})
# dirty hack to be able to know which ogre libraries are defined by the
# absolute paths. These variables are sometimes multi-configuration vars
# (i.e: C:/vcpkg/installed/x64-windows$<$:/debug>/..)
# IS_ABSOLUTE cmake function seems not to be working fine with them.
string(SUBSTRING "${OGRE_LIBRARY_DIRS}" 0 5 PATH_PREFIX)
string(SUBSTRING "${ogre_lib}" 0 5 ogrelib_PATH_PREFIX)
if(ogrelib_PATH_PREFIX STREQUAL PATH_PREFIX)
set(lib_fullpath "${ogre_lib}")
else()
string(REGEX REPLACE "\\$.*>" "" ogre_lib ${ogre_lib})
# Be sure that all Ogre* libraries are using absolute paths
set(prefix "")
# vcpkg uses special directory (lib/manual-link/) to place libraries
# with main sysmbol like OgreMain.
if(ogre_lib MATCHES "OgreMain" AND NOT IS_ABSOLUTE "${ogre_lib}" AND EXISTS "${OGRE_LIBRARY_DIRS}/manual-link/")
set(prefix "${OGRE_LIBRARY_DIRS}/manual-link/")
elseif(ogre_lib MATCHES "Ogre" AND NOT IS_ABSOLUTE "${ogre_lib}")
set(prefix "${OGRE_LIBRARY_DIRS}/")
endif()
if(ogre_lib MATCHES "Plugin_" OR ogre_lib MATCHES "RenderSystem_")
if(NOT IS_ABSOLUTE "${ogre_lib}")
set(prefix "${OGRE_LIBRARY_DIRS}/OGRE/")
endif()
endif()
# Some Ogre libraries are not using the .lib extension
set(postfix "")
if(NOT ogre_lib MATCHES ".lib$")
# Do not consider imported targets as libraries
if(NOT ogre_lib MATCHES "::")
set(postfix ".lib")
endif()
endif()
set(lib_fullpath "${prefix}${ogre_lib}${postfix}")
endif()
list(APPEND ogre_all_libs ${lib_fullpath})
endforeach()
set(OGRE_LIBRARIES ${ogre_all_libs})
set(OGRE_RESOURCE_PATH ${OGRE_CONFIG_DIR})
endif()
endif()
set(IgnOGRE_FOUND false)
if(OGRE_FOUND)
set(IgnOGRE_FOUND true)
# manually search and append the the RenderSystem/GL path to
# OGRE_INCLUDE_DIRS so OGRE GL headers can be found
foreach(dir ${OGRE_INCLUDE_DIRS})
get_filename_component(dir_name "${dir}" NAME)
if("${dir_name}" STREQUAL "OGRE")
if(${OGRE_VERSION} VERSION_LESS 1.11.0)
set(dir_include "${dir}/RenderSystems/GL")
else()
set(dir_include "${dir}/RenderSystems/GL" "${dir}/Paging")
endif()
else()
set(dir_include "${dir}")
endif()
list(APPEND OGRE_INCLUDE_DIRS ${dir_include})
endforeach()
include(IgnImportTarget)
ign_import_target(IgnOGRE
TARGET_NAME IgnOGRE::IgnOGRE
LIB_VAR OGRE_LIBRARIES
INCLUDE_VAR OGRE_INCLUDE_DIRS)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnBenchmark.cmake 0000664 0001750 0001750 00000006717 14160533245 023041 0 ustar jrivero jrivero #.rst
# IgnBenchmark
# ------------
#
# ign_add_version_info_target()
#
# Adds a target to generate build and system configuration information.
#
# ign_add_benchmarks()
#
# Adds a target to execute all available benchmarks and aggregate the results.
#
# USAGE:
# 1. Add the following line to your CMakeLists.txt
# include(IgnBenchmark)
#
# 2. Add the benchmark
# ign_add_benchmarks(SOURCES ${benchmark_sources_list})
#
# 3. After building the project, use `make run_benchmarks` to execute and
# aggregate benchmark results to ${CMAKE_BINARY_DIR}/benchmark_results
#
#===============================================================================
# Copyright (C) 2019 Open Source Robotics Foundation
#
# Licensed 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.
function(ign_add_version_info_target)
# generate a version_info.json file that can be used to embed project
# version information
# While this command may look a bit unweildy, it creates a target
# that forces the file to be regenerated at build time.
add_custom_target(version_info_target
COMMAND ${CMAKE_COMMAND}
-Dinput_file=${IGNITION_CMAKE_DIR}/version_info.json.in
-Doutput_file=${CMAKE_CURRENT_BINARY_DIR}/version_info.json
-Drepository_root=${CMAKE_CURRENT_SOURCE_DIR}
# Yes, these variables need to be passed in, because they won't
# get properly set when invoked as a CMake script.
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DPROJECT_VERSION=${PROJECT_VERSION}
-DPROJECT_VERSION_FULL=${PROJECT_VERSION_FULL}
-DPROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
-DPROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR}
-DPROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH}
-DPROJECT_NAME=${PROJECT_NAME}
-P ${IGNITION_CMAKE_DIR}/IgnGenerateVersionInfo.cmake
)
endfunction()
function(ign_add_benchmarks)
cmake_parse_arguments(BENCHMARK "" "" "SOURCES" ${ARGN})
if(NOT BUILD_TESTING)
return()
endif()
find_package(benchmark)
if(NOT benchmark_FOUND)
message(WARNING "Unable to find google benchmark (libbenchmark-dev). Disabling benchmarks.")
return()
endif()
ign_build_executables(
PREFIX "BENCHMARK_"
SOURCES ${BENCHMARK_SOURCES}
LIB_DEPS benchmark::benchmark
EXEC_LIST BENCHMARK_TARGETS
)
set(BENCHMARK_TARGETS_LIST "")
foreach(benchmark ${BENCHMARK_TARGETS})
list(APPEND BENCHMARK_TARGETS_LIST "$")
endforeach()
ign_add_version_info_target()
file(GENERATE
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/benchmark_targets"
CONTENT
"${BENCHMARK_TARGETS_LIST}")
add_custom_target(
run_benchmarks
COMMAND python3 ${IGNITION_CMAKE_BENCHMARK_DIR}/run_benchmarks.py
--project-name ${PROJECT_NAME}
--version-file ${CMAKE_CURRENT_BINARY_DIR}/version_info.json
--benchmark-targets ${CMAKE_CURRENT_BINARY_DIR}/benchmark_targets
--results-root ${CMAKE_BINARY_DIR}/benchmark_results
)
add_dependencies(run_benchmarks ${BENCHMARK_TARGETS} version_info_target)
endfunction()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindGTS.cmake 0000664 0001750 0001750 00000005474 14160533245 021746 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 GNU Triangulation Surface Library
if (NOT WIN32)
# Configuration using pkg-config modules
include(IgnPkgConfig)
ign_pkg_check_modules(GTS gts)
else()
# true by default, change to false when a failure appears
set(GTS_FOUND true)
# 1. look for GTS headers
find_path(GTS_INCLUDE_DIRS gts.h
hints
${CMAKE_FIND_ROOT_PATH}
paths
${CMAKE_FIND_ROOT_PATH}
doc "GTS header include dir"
path_suffixes
include
)
if (GTS_INCLUDE_DIRS)
if(NOT GTS_FIND_QUIETLY)
message(STATUS "Looking for gts.h gtsconfig.h - found")
endif()
else()
if(NOT GTS_FIND_QUIETLY)
message(STATUS "Looking for gts.h gtsconfig.h - not found")
endif()
set(GTS_FOUND false)
endif()
mark_as_advanced(GTS_INCLUDE_DIRS)
# 2. look for GTS libraries
find_library(GTS_LIBRARIES gts)
mark_as_advanced(GTS_LIBRARIES)
if (GTS_LIBRARIES)
if(NOT GTS_FIND_QUIETLY)
message(STATUS "Looking for gts library - found")
endif()
else()
if(NOT GTS_FIND_QUIETLY)
message(STATUS "Looking for gts library - not found")
endif()
set (GTS_FOUND false)
endif()
# 2.1 Need glib library
find_library(GLIB_LIBRARY glib-2.0)
if (NOT GLIB_LIBRARY)
if(NOT GTS_FIND_QUIETLY)
message(STATUS "Looking for glib library - not found")
endif()
else()
if(NOT GTS_FIND_QUIETLY)
message(STATUS "Looking for glib library - found")
endif()
endif()
find_path(GLIB_INCLUDE_DIR
NAMES glib.h
PATH_SUFFIXES glib-2.0)
if (GLIB_INCLUDE_DIR)
list(APPEND GTS_INCLUDE_DIRS "${GLIB_INCLUDE_DIR}")
endif()
find_path(GLIBCONFIG_INCLUDE_DIR
NAMES glibconfig.h
PATH_SUFFIXES lib/glib-2.0/include)
if (GLIBCONFIG_INCLUDE_DIR)
list(APPEND GTS_INCLUDE_DIRS "${GLIBCONFIG_INCLUDE_DIR}")
endif()
list(APPEND GTS_LIBRARIES "${GLIB_LIBRARY}")
if (GTS_FOUND)
# We need to manually specify the pkgconfig entry (and type of entry),
# because ign_pkg_check_modules does not work for it.
include(IgnPkgConfig)
ign_pkg_config_library_entry(GTS gts)
include(IgnImportTarget)
ign_import_target(GTS)
endif()
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindIgnURDFDOM.cmake 0000664 0001750 0001750 00000003310 14160533245 023032 0 ustar jrivero jrivero #
# Copyright (C) 2021 Open Source Robotics Foundation
#
# Licensed 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.
#
# Prefer pkg-config over cmake if possible since version checking is not working
# on urdfdom series from 1.x to 3.0.0 (at least)
include(IgnPkgConfig)
if(PKG_CONFIG_FOUND)
if (IgnURDFDOM_FIND_VERSION)
set(signature "urdfdom >= ${IgnURDFDOM_FIND_VERSION}")
else()
set(signature "urdfdom")
endif()
ign_pkg_check_modules(IgnURDFDOM "${signature}")
else()
message(VERBOSE "Unable to find pkg-config in the system, fallback to use CMake")
endif()
if(NOT IgnURDFDOM_FOUND)
if(IgnURDFDOM_FIND_VERSION)
set(find_version VERSION ${IgnURDFDOM_FIND_VERSION})
else()
set(find_version "")
endif()
# NOTE: urdfdom cmake does not support version checking
ign_find_package(urdfdom ${find_version} QUIET)
if (urdfdom_FOUND)
add_library(IgnURDFDOM::IgnURDFDOM INTERFACE IMPORTED)
target_link_libraries(IgnURDFDOM::IgnURDFDOM
INTERFACE
urdfdom::urdfdom_model
urdfdom::urdfdom_world
urdfdom::urdfdom_sensor
urdfdom::urdfdom_model_state
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(IgnURDFDOM DEFAULT_MSG)
endif()
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindFreeImage.cmake 0000664 0001750 0001750 00000011202 14160533245 023117 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 FreeImage
# Grab the version numbers requested by the call to find_package(~)
set(major_version ${FreeImage_FIND_VERSION_MAJOR})
set(minor_version ${FreeImage_FIND_VERSION_MINOR})
# Set the full version number
set(full_version ${major_version}.${minor_version})
if (NOT WIN32)
include(IgnPkgConfig)
ign_pkg_config_library_entry(FreeImage freeimage)
# If we don't have PkgConfig, or if PkgConfig failed, then do a manual search
if(NOT FreeImage_FOUND)
find_path(FreeImage_INCLUDE_DIRS FreeImage.h)
if(NOT FreeImage_INCLUDE_DIRS)
if(NOT FreeImage_FIND_QUIETLY)
message(STATUS "Looking for FreeImage.h - not found")
message(STATUS "Missing: Unable to find FreeImage.h")
endif()
else(NOT FreeImage_INCLUDE_DIRS)
# Check the FreeImage header for the right version
set(testFreeImageSource ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/test_freeimage.c)
set(FreeImage_test_output "")
set(FreeImage_compile_output "")
file(WRITE ${testFreeImageSource}
"#include \nint main () { if (FREEIMAGE_MAJOR_VERSION >= ${major_version} && FREEIMAGE_MINOR_VERSION >= ${minor_version}) return 1; else return 0;} \n")
try_run(FREEIMAGE_RUNS
FREEIMAGE_COMPILES
${CMAKE_CURRENT_BINARY_DIR}
${testFreeImageSource}
CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${FreeImage_INCLUDE_DIRS}
RUN_OUTPUT_VARIABLE FreeImage_test_output
COMPILE_OUTPUT_VARIABLE FreeImage_compile_output)
if(NOT FREEIMAGE_COMPILES)
if(NOT FreeImage_FIND_QUIETLY)
message(STATUS "FreeImage test failed to compile - This may indicate a build system bug")
endif()
return()
endif(NOT FREEIMAGE_COMPILES)
if(NOT FREEIMAGE_RUNS)
if(NOT FreeImage_FIND_QUIETLY)
message(STATUS "Invalid FreeImage Version. Requires ${major_version}.${minor_version}")
endif()
endif(NOT FREEIMAGE_RUNS)
endif(NOT FreeImage_INCLUDE_DIRS)
mark_as_advanced(FreeImage_INCLUDE_DIRS)
find_library(FreeImage_LIBRARIES NAMES freeimage FreeImage)
if(FreeImage_LIBRARIES)
set(FreeImage_FOUND true)
else()
if(NOT FreeImage_FIND_QUIELTY)
message(STATUS "Missing: Unable to find libfreeimage")
endif()
endif(FreeImage_LIBRARIES)
mark_as_advanced(FreeImage_LIBRARIES)
endif()
if(FreeImage_FOUND)
# Create the imported target for FreeImage if we found it
include(IgnImportTarget)
ign_import_target(FreeImage)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
FreeImage
REQUIRED_VARS FreeImage_FOUND)
else()
# true by default, change to false when a failure appears
set(FreeImage_FOUND true)
# 1. look for FreeImage headers
find_path(FreeImage_INCLUDE_DIRS FreeImage.h
hints
${CMAKE_FIND_ROOT_PATH}
paths
${CMAKE_FIND_ROOT_PATH}
doc "FreeImage header include dir"
path_suffixes
include
)
if (FreeImage_INCLUDE_DIRS)
if(NOT FreeImage_FIND_QUIETLY)
message(STATUS "Looking for FreeImage.h FreeImageconfig.h - found")
endif()
else()
if(NOT FreeImage_FIND_QUIETLY)
message(STATUS "Looking for FreeImage.h FreeImageconfig.h - not found")
endif()
set(FreeImage_FOUND false)
endif()
mark_as_advanced(FreeImage_INCLUDE_DIRS)
# 2. look for FreeImage libraries
find_library(FreeImage_LIBRARIES FreeImage)
mark_as_advanced(FreeImage_LIBRARIES)
if (FreeImage_LIBRARIES)
if(NOT FreeImage_FIND_QUIETLY)
message(STATUS "Looking for FreeImage library - found")
endif()
else()
if(NOT FreeImage_FIND_QUIETLY)
message(STATUS "Looking for FreeImage library - not found")
endif()
set (FreeImage_FOUND false)
endif()
if (FreeImage_FOUND)
include(IgnPkgConfig)
ign_pkg_config_library_entry(FreeImage "FreeImage")
include(IgnImportTarget)
ign_import_target(FreeImage)
endif()
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindCPPZMQ.cmake 0000664 0001750 0001750 00000004155 14160533245 022316 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 cppzmq
#
# Usage of this module as follows:
#
# find_package(CPPZMQ)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# CPPZMQ_HEADER_PATH Set this variable to the location of the zmp.hpp
# header file if the module has problems finding it.
# ZeroMQ_INCLUDE_DIRS Set this variable to the include directories of
# ZeroMQ if the module has problems finding
# the proper installation path.
#
# Variables defined by this module:
#
# CPPZMQ_FOUND System has CPPZMQ header
# CPPZMQ_INCLUDE_DIRS The location of zmq.hpp header
# If we cannot find the header, we will switch this to false
set(CPPZMQ_FOUND true)
# Search for the header
find_path(CPPZMQ_INCLUDE_DIRS zmq.hpp
PATHS
${ZeroMQ_INCLUDE_DIRS}
${CPPZMQ_HEADER_PATH})
mark_as_advanced(CPPZMQ_INCLUDE_DIRS)
if(NOT CPPZMQ_INCLUDE_DIRS)
set(CPPZMQ_FOUND false)
endif()
if(CPPZMQ_FOUND)
include(IgnImportTarget)
# Since this is a header-only library, we should import it as an INTERFACE
# target.
ign_import_target(CPPZMQ INTERFACE)
# Now, to use the CPPZMQ headers, you should call
# target_link_libraries( CPPZMQ::CPPZMQ) instead of using
# target_include_directories(~)
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/cmake_uninstall.cmake.in 0000664 0001750 0001750 00000002023 14160533245 024251 0 ustar jrivero jrivero if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: '@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt'")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling '$ENV{DESTDIR}${file}'")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing '$ENV{DESTDIR}${file}'")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File '$ENV{DESTDIR}${file}' does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)
ign-cmake-ignition-cmake2_2.10.0/cmake/ignition-all-config.cmake.in 0000664 0001750 0001750 00000003654 14160533245 024744 0 ustar jrivero jrivero # - Config to retrieve all components of the @PKG_NAME@ package
#
# This should only be invoked by @PKG_NAME@-config.cmake.
#
# To retrieve this meta-package, use:
# find_package(@PKG_NAME@ COMPONENTS all)
#
# This creates the target @ign_namespace@all which will link to all known
# components of @PKG_NAME@, including the core library.
#
# This also creates the variable @PKG_NAME@_ALL_LIBRARIES
#
################################################################################
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
if(@PKG_NAME@_ALL_CONFIG_INCLUDED)
return()
endif()
set(@PKG_NAME@_ALL_CONFIG_INCLUDED TRUE)
if(NOT @all_pkg_name@_FIND_QUIETLY)
message(STATUS "Looking for all libraries of @PKG_NAME@ -- found version @PROJECT_VERSION_FULL@")
endif()
@PACKAGE_INIT@
# Get access to the find_dependency utility
include(CMakeFindDependencyMacro)
# Find the core library
find_dependency(@PKG_NAME@ @PROJECT_VERSION_FULL_NO_SUFFIX@ EXACT)
# Find the component libraries
@find_all_pkg_components@
if(NOT TARGET @import_target_name@)
include("${CMAKE_CURRENT_LIST_DIR}/@target_output_filename@")
add_library(@simple_import_name@ INTERFACE IMPORTED)
set_target_properties(@simple_import_name@ PROPERTIES
INTERFACE_LINK_LIBRARIES "@import_target_name@")
endif()
# Create the "requested" target if it does not already exist
if(NOT TARGET @ign_namespace@requested)
add_library(@ign_namespace@requested INTERFACE IMPORTED)
endif()
# Link the "all" target to the "requested" target
get_target_property(ign_requested_components @ign_namespace@requested INTERFACE_LINK_LIBRARIES)
if(NOT ign_requested_components)
set_target_properties(@ign_namespace@requested PROPERTIES
INTERFACE_LINK_LIBRARIES "@import_target_name@")
else()
set_target_properties(@ign_namespace@requested PROPERTIES
INTERFACE_LINK_LIBRARIES "${ign_requested_components};@import_target_name@")
endif()
set(@PKG_NAME@_ALL_LIBRARIES @import_target_name@)
ign-cmake-ignition-cmake2_2.10.0/cmake/IgnRonn2Man.cmake 0000664 0001750 0001750 00000003754 14160533245 022577 0 ustar jrivero jrivero #
# Based on work of Emmanuel Roullit
# Copyright 2009, 2012 Emmanuel Roullit.
# Subject to the GPL, version 2.
#
# 2017-09-13
# - Tweaked macro name to avoid name collisions
#
MACRO(IGN_ADD_MANPAGE_TARGET)
# It is not possible add a dependency to target 'install'
# Run hard-coded 'make man' when 'make install' is invoked
INSTALL(CODE "EXECUTE_PROCESS(COMMAND $(MAKE) man)")
ADD_CUSTOM_TARGET(man)
ENDMACRO(IGN_ADD_MANPAGE_TARGET)
FIND_PROGRAM(RONN ronn)
FIND_PROGRAM(GZIP gzip)
IF (NOT RONN OR NOT GZIP)
IF (NOT RONN)
IGN_BUILD_WARNING ("ronn not found, manpages won't be generated")
ENDIF(NOT RONN)
IF (NOT GZIP)
IGN_BUILD_WARNING ("gzip not found, manpages won't be generated")
ENDIF(NOT GZIP)
# empty macro
MACRO(manpage MANFILE)
ENDMACRO(manpage)
SET (MANPAGES_SUPPORT FALSE)
ELSE (NOT RONN OR NOT GZIP)
MESSAGE (STATUS "Looking for ronn to generate manpages - found")
SET (MANPAGES_SUPPORT TRUE)
MACRO(manpage RONNFILE SECTION)
SET(RONNFILE_FULL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${RONNFILE})
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}
DEPENDS ${RONNFILE}
COMMAND ${RONN}
ARGS -r --pipe ${RONNFILE_FULL_PATH}.${SECTION}.ronn
> ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}
)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}.gz
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}
COMMAND ${GZIP} -c ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}
> ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}.gz
)
SET(MANPAGE_TARGET "man-${RONNFILE}")
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}.gz)
ADD_DEPENDENCIES(man ${MANPAGE_TARGET})
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${RONNFILE}.${SECTION}.gz
DESTINATION share/man/man${SECTION}
)
ENDMACRO(manpage RONNFILE SECTION)
ENDIF(NOT RONN OR NOT GZIP)
ign-cmake-ignition-cmake2_2.10.0/cmake/FindZeroMQ.cmake 0000664 0001750 0001750 00000006442 14160533245 022462 0 ustar jrivero jrivero ##=============================================================================
#
# CMake - Cross Platform Makefile Generator
# Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
# nor the names of their contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Modified by Jose Luis Rivero
#
##=============================================================================
# - Try to find ZeroMQ headers and libraries
#
# Usage of this module as follows:
#
# find_package(ZeroMQ)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# ZeroMQ_ROOT_DIR Set this variable to the root installation of
# ZeroMQ if the module has problems finding
# the proper installation path.
#
# Variables defined by this module:
#
# ZEROMQ_FOUND System has ZeroMQ libs/headers
# ZeroMQ_LIBRARIES The ZeroMQ libraries
# ZeroMQ_INCLUDE_DIRS The location of ZeroMQ headers
include(IgnPkgConfig)
# We initialize this variable to the default target name
set(ZeroMQ_TARGET ZeroMQ::ZeroMQ)
find_package(ZeroMQ ${ZeroMQ_FIND_VERSION} QUIET CONFIG)
if (ZeroMQ_FOUND)
# ZeroMQ's cmake script imports its own target, so we'll
# overwrite the default with the name of theirs. In the
# future, we should be able to use a target alias instead.
set(ZeroMQ_TARGET libzmq)
# Make sure to fill out the pkg-config information before quitting
ign_pkg_config_entry(ZeroMQ "libzmq >= ${ZeroMQ_FIND_VERSION}")
return()
endif()
if (UNIX)
if(NOT ZeroMQ_FIND_QUIETLY)
message(STATUS "Config-file not installed for ZeroMQ -- checking for pkg-config")
endif()
ign_pkg_check_modules(ZeroMQ "libzmq >= ${ZeroMQ_FIND_VERSION}")
endif()
ign-cmake-ignition-cmake2_2.10.0/cmake/FindAVUTIL.cmake 0000664 0001750 0001750 00000002115 14160533245 022302 0 ustar jrivero jrivero #===============================================================================
# Copyright (C) 2017 Open Source Robotics Foundation
#
# Licensed 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 avutil
include(IgnPkgConfig)
ign_pkg_check_modules_quiet(AVUTIL libavutil)
if(NOT AVUTIL_FOUND)
include(IgnManualSearch)
ign_manual_search(AVUTIL
HEADER_NAMES "libavutil/avutil.h"
LIBRARY_NAMES "avutil")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
AVUTIL
REQUIRED_VARS AVUTIL_FOUND)
ign-cmake-ignition-cmake2_2.10.0/cmake/upload_doc.sh.in 0000664 0001750 0001750 00000002523 14160533245 022550 0 ustar jrivero jrivero #!/bin/sh
echo "Usage: sh upload_doc.sh [y/n]"
echo " Optional [y/n] argument indicates whether to upload the docs to S3 automatically."
# Check if the node was configured to use s3cmd
# This is done by running s3cmd --configure
if [ ! -f "${HOME}/.s3cfg" ]; then
echo "No $HOME/.s3cfg file found. Please config the software first in your system"
exit 1
fi
# Make documentation if not build
if [ ! -f "@CMAKE_BINARY_DIR@/doxygen/html/index.html" ]; then
make doc
if [ ! -f "@CMAKE_BINARY_DIR@/doxygen/html/index.html" ]; then
echo "Documentation not present. Install doxygen, and run `make doc` in the build directory"
exit 1
fi
fi
# Dry run
s3cmd sync --dry-run @CMAKE_BINARY_DIR@/doxygen/html/ s3://ignitionrobotics.org/api/@IGN_DESIGNATION@/@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@/ -v
if [ -z "$1" ]; then
echo -n "Upload (Y/n)? "
read ans
else
ans=$1
fi
if [ "$ans" = "n" ] || [ "$ans" = "N" ]; then
exit 1
else
s3cmd sync @CMAKE_BINARY_DIR@/doxygen/html/ s3://ignitionrobotics.org/api/@IGN_DESIGNATION@/@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@/ -v
echo "WARNING"
echo " A CloudFront invalidation is required. Run the following command with the appropriate \$CLOUDFRONT_DISTRIBUTION_ID:\n"
echo " aws cloudfront create-invalidation --distribution-id \$CLOUDFRONT_DISTRIBUTION_ID --paths '/*'"
fi
ign-cmake-ignition-cmake2_2.10.0/tutorials.md.in 0000664 0001750 0001750 00000001230 14160533245 021365 0 ustar jrivero jrivero \page tutorials Tutorials
Welcome to the Ignition @IGN_DESIGNATION_CAP@ tutorials. These tutorials
will guide you through the process of understanding the capabilities of the
Ignition @IGN_DESIGNATION_CAP@ library and how to use the library effectively.
**The tutorials**
1. \subpage install "Installation"
1. \subpage developingwithcmake "Developing with Ignition CMake"
## License
The code associated with this documentation is licensed under an [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0).
This documentation is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/).
ign-cmake-ignition-cmake2_2.10.0/codecheck/ 0000775 0001750 0001750 00000000000 14160533245 020324 5 ustar jrivero jrivero ign-cmake-ignition-cmake2_2.10.0/codecheck/namespace_AZ.rule 0000664 0001750 0001750 00000000406 14160533245 023543 0 ustar jrivero jrivero
:: _[A-Z]_AZnamingwarningIdentifier that starts with underscore and then a capital letter is reserved.
ign-cmake-ignition-cmake2_2.10.0/codecheck/header_guard.rule 0000664 0001750 0001750 00000000445 14160533245 023632 0 ustar jrivero jrivero
define#define _[A-Z]_AZdefinewarningDefinitions should not start with underscore and then a capital letter.
ign-cmake-ignition-cmake2_2.10.0/codecheck/cpplint.py 0000664 0001750 0001750 00001001135 14160533245 022350 0 ustar jrivero jrivero #!/usr/bin/env python
#
# Copyright (c) 2009 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Imported from https://github.com/cpplint/cpplint:
# https://github.com/cpplint/cpplint/blob/0f2319741f3407d8638cdc7c41e4fc9bad217f68/cpplint.py
"""Does google-lint on c++ files.
The goal of this script is to identify places in the code that *may*
be in non-compliance with google style. It does not attempt to fix
up these problems -- the point is to educate. It does also not
attempt to find all problems, or to ensure that everything it does
find is legitimately a problem.
In particular, we can get very confused by /* and // inside strings!
We do a small hack, which is to ignore //'s with "'s after them on the
same line, but it is far from perfect (in either direction).
"""
import codecs
import copy
import getopt
import glob
import itertools
import math # for log
import os
import re
import sre_compile
import string
import sys
import sysconfig
import unicodedata
import xml.etree.ElementTree
# if empty, use defaults
_valid_extensions = set([])
__VERSION__ = '1.5.4'
try:
xrange # Python 2
except NameError:
# -- pylint: disable=redefined-builtin
xrange = range # Python 3
_USAGE = """
Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit|sed|gsed]
[--filter=-x,+y,...]
[--counting=total|toplevel|detailed] [--root=subdir]
[--repository=path]
[--linelength=digits] [--headers=x,y,...]
[--recursive]
[--exclude=path]
[--extensions=hpp,cpp,...]
[--includeorder=default|standardcfirst]
[--quiet]
[--version]
[file] ...
Style checker for C/C++ source files.
This is a fork of the Google style checker with minor extensions.
The style guidelines this tries to follow are those in
https://google.github.io/styleguide/cppguide.html
Every problem is given a confidence score from 1-5, with 5 meaning we are
certain of the problem, and 1 meaning it could be a legitimate construct.
This will miss some errors, and is not a substitute for a code review.
To suppress false-positive errors of a certain category, add a
'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
suppresses errors of all categories on that line.
The files passed in will be linted; at least one file must be provided.
Default linted extensions are %s.
Other file types will be ignored.
Change the extensions with the --extensions flag.
Flags:
output=emacs|eclipse|vs7|junit|sed|gsed
By default, the output is formatted to ease emacs parsing. Visual Studio
compatible output (vs7) may also be used. Further support exists for
eclipse (eclipse), and JUnit (junit). XML parsers such as those used
in Jenkins and Bamboo may also be used.
The sed format outputs sed commands that should fix some of the errors.
Note that this requires gnu sed. If that is installed as gsed on your
system (common e.g. on macOS with homebrew) you can use the gsed output
format. Sed commands are written to stdout, not stderr, so you should be
able to pipe output straight to a shell to run the fixes.
verbose=#
Specify a number 0-5 to restrict errors to certain verbosity levels.
Errors with lower verbosity levels have lower confidence and are more
likely to be false positives.
quiet
Don't print anything if no errors are found.
filter=-x,+y,...
Specify a comma-separated list of category-filters to apply: only
error messages whose category names pass the filters will be printed.
(Category names are printed with the message and look like
"[whitespace/indent]".) Filters are evaluated left to right.
"-FOO" and "FOO" means "do not print categories that start with FOO".
"+FOO" means "do print categories that start with FOO".
Examples: --filter=-whitespace,+whitespace/braces
--filter=whitespace,runtime/printf,+runtime/printf_format
--filter=-,+build/include_what_you_use
To see a list of all the categories used in cpplint, pass no arg:
--filter=
counting=total|toplevel|detailed
The total number of errors found is always printed. If
'toplevel' is provided, then the count of errors in each of
the top-level categories like 'build' and 'whitespace' will
also be printed. If 'detailed' is provided, then a count
is provided for each category like 'build/class'.
repository=path
The top level directory of the repository, used to derive the header
guard CPP variable. By default, this is determined by searching for a
path that contains .git, .hg, or .svn. When this flag is specified, the
given path is used instead. This option allows the header guard CPP
variable to remain consistent even if members of a team have different
repository root directories (such as when checking out a subdirectory
with SVN). In addition, users of non-mainstream version control systems
can use this flag to ensure readable header guard CPP variables.
Examples:
Assuming that Alice checks out ProjectName and Bob checks out
ProjectName/trunk and trunk contains src/chrome/ui/browser.h, then
with no --repository flag, the header guard CPP variable will be:
Alice => TRUNK_SRC_CHROME_BROWSER_UI_BROWSER_H_
Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_
If Alice uses the --repository=trunk flag and Bob omits the flag or
uses --repository=. then the header guard CPP variable will be:
Alice => SRC_CHROME_BROWSER_UI_BROWSER_H_
Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_
root=subdir
The root directory used for deriving header guard CPP variable.
This directory is relative to the top level directory of the repository
which by default is determined by searching for a directory that contains
.git, .hg, or .svn but can also be controlled with the --repository flag.
If the specified directory does not exist, this flag is ignored.
Examples:
Assuming that src is the top level directory of the repository (and
cwd=top/src), the header guard CPP variables for
src/chrome/browser/ui/browser.h are:
No flag => CHROME_BROWSER_UI_BROWSER_H_
--root=chrome => BROWSER_UI_BROWSER_H_
--root=chrome/browser => UI_BROWSER_H_
--root=.. => SRC_CHROME_BROWSER_UI_BROWSER_H_
linelength=digits
This is the allowed line length for the project. The default value is
80 characters.
Examples:
--linelength=120
recursive
Search for files to lint recursively. Each directory given in the list
of files to be linted is replaced by all files that descend from that
directory. Files with extensions not in the valid extensions list are
excluded.
exclude=path
Exclude the given path from the list of files to be linted. Relative
paths are evaluated relative to the current directory and shell globbing
is performed. This flag can be provided multiple times to exclude
multiple files.
Examples:
--exclude=one.cc
--exclude=src/*.cc
--exclude=src/*.cc --exclude=test/*.cc
extensions=extension,extension,...
The allowed file extensions that cpplint will check
Examples:
--extensions=%s
includeorder=default|standardcfirst
For the build/include_order rule, the default is to blindly assume angle
bracket includes with file extension are c-system-headers (default),
even knowing this will have false classifications.
The default is established at google.
standardcfirst means to instead use an allow-list of known c headers and
treat all others as separate group of "other system headers". The C headers
included are those of the C-standard lib and closely related ones.
headers=x,y,...
The header extensions that cpplint will treat as .h in checks. Values are
automatically added to --extensions list.
(by default, only files with extensions %s will be assumed to be headers)
Examples:
--headers=%s
--headers=hpp,hxx
--headers=hpp
cpplint.py supports per-directory configurations specified in CPPLINT.cfg
files. CPPLINT.cfg file can contain a number of key=value pairs.
Currently the following options are supported:
set noparent
filter=+filter1,-filter2,...
exclude_files=regex
linelength=80
root=subdir
headers=x,y,...
"set noparent" option prevents cpplint from traversing directory tree
upwards looking for more .cfg files in parent directories. This option
is usually placed in the top-level project directory.
The "filter" option is similar in function to --filter flag. It specifies
message filters in addition to the |_DEFAULT_FILTERS| and those specified
through --filter command-line flag.
"exclude_files" allows to specify a regular expression to be matched against
a file name. If the expression matches, the file is skipped and not run
through the linter.
"linelength" allows to specify the allowed line length for the project.
The "root" option is similar in function to the --root flag (see example
above). Paths are relative to the directory of the CPPLINT.cfg.
The "headers" option is similar in function to the --headers flag
(see example above).
CPPLINT.cfg has an effect on files in the same directory and all
sub-directories, unless overridden by a nested configuration file.
Example file:
filter=-build/include_order,+build/include_alpha
exclude_files=.*\\.cc
The above example disables build/include_order warning and enables
build/include_alpha as well as excludes all .cc from being
processed by linter, in the current directory (where the .cfg
file is located) and all sub-directories.
"""
# We categorize each error message we print. Here are the categories.
# We want an explicit list so we can list them all in cpplint --filter=.
# If you add a new error message with a new category, add it to the list
# here! cpplint_unittest.py should tell you if you forget to do this.
_ERROR_CATEGORIES = [
'build/class',
'build/c++11',
'build/c++14',
'build/c++tr1',
'build/deprecated',
'build/endif_comment',
'build/explicit_make_pair',
'build/forward_decl',
'build/header_guard',
'build/include',
'build/include_subdir',
'build/include_alpha',
'build/include_order',
'build/include_what_you_use',
'build/namespaces_headers',
'build/namespaces_literals',
'build/namespaces',
'build/printf_format',
'build/storage_class',
'legal/copyright',
'readability/alt_tokens',
'readability/braces',
'readability/casting',
'readability/check',
'readability/constructors',
'readability/fn_size',
'readability/inheritance',
'readability/multiline_comment',
'readability/multiline_string',
'readability/namespace',
'readability/nolint',
'readability/nul',
'readability/strings',
'readability/todo',
'readability/utf8',
'runtime/arrays',
'runtime/casting',
'runtime/explicit',
'runtime/int',
'runtime/init',
'runtime/invalid_increment',
'runtime/member_string_references',
'runtime/memset',
'runtime/indentation_namespace',
'runtime/operator',
'runtime/printf',
'runtime/printf_format',
'runtime/references',
'runtime/string',
'runtime/threadsafe_fn',
'runtime/vlog',
'whitespace/blank_line',
'whitespace/braces',
'whitespace/comma',
'whitespace/comments',
'whitespace/empty_conditional_body',
'whitespace/empty_if_body',
'whitespace/empty_loop_body',
'whitespace/end_of_line',
'whitespace/ending_newline',
'whitespace/forcolon',
'whitespace/indent',
'whitespace/line_length',
'whitespace/newline',
'whitespace/operators',
'whitespace/parens',
'whitespace/semicolon',
'whitespace/tab',
'whitespace/todo',
]
# keywords to use with --outputs which generate stdout for machine processing
_MACHINE_OUTPUTS = [
'junit',
'sed',
'gsed'
]
# These error categories are no longer enforced by cpplint, but for backwards-
# compatibility they may still appear in NOLINT comments.
_LEGACY_ERROR_CATEGORIES = [
'readability/streams',
'readability/function',
]
# The default state of the category filter. This is overridden by the --filter=
# flag. By default all errors are on, so only add here categories that should be
# off by default (i.e., categories that must be enabled by the --filter= flags).
# All entries here should start with a '-' or '+', as in the --filter= flag.
_DEFAULT_FILTERS = [
'-build/c++11',
'-build/header_guard',
'-build/include_alpha',
'-build/include_order',
'-build/include_subdir',
'-build/namespaces',
'-readability/namespace',
'-runtime/indentation_namespace',
'-runtime/references',
'-whitespace/blank_line',
'-whitespace/braces',
'-whitespace/indent',
'-whitespace/newline',
'-whitespace/parens',
]
# The default list of categories suppressed for C (not C++) files.
_DEFAULT_C_SUPPRESSED_CATEGORIES = [
'readability/casting',
]
# The default list of categories suppressed for Linux Kernel files.
_DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
'whitespace/tab',
]
# We used to check for high-bit characters, but after much discussion we
# decided those were OK, as long as they were in UTF-8 and didn't represent
# hard-coded international strings, which belong in a separate i18n file.
# C++ headers
_CPP_HEADERS = frozenset([
# Legacy
'algobase.h',
'algo.h',
'alloc.h',
'builtinbuf.h',
'bvector.h',
'complex.h',
'defalloc.h',
'deque.h',
'editbuf.h',
'fstream.h',
'function.h',
'hash_map',
'hash_map.h',
'hash_set',
'hash_set.h',
'hashtable.h',
'heap.h',
'indstream.h',
'iomanip.h',
'iostream.h',
'istream.h',
'iterator.h',
'list.h',
'map.h',
'multimap.h',
'multiset.h',
'ostream.h',
'pair.h',
'parsestream.h',
'pfstream.h',
'procbuf.h',
'pthread_alloc',
'pthread_alloc.h',
'rope',
'rope.h',
'ropeimpl.h',
'set.h',
'slist',
'slist.h',
'stack.h',
'stdiostream.h',
'stl_alloc.h',
'stl_relops.h',
'streambuf.h',
'stream.h',
'strfile.h',
'strstream.h',
'tempbuf.h',
'tree.h',
'type_traits.h',
'vector.h',
# 17.6.1.2 C++ library headers
'algorithm',
'array',
'atomic',
'bitset',
'chrono',
'codecvt',
'complex',
'condition_variable',
'deque',
'exception',
'forward_list',
'fstream',
'functional',
'future',
'initializer_list',
'iomanip',
'ios',
'iosfwd',
'iostream',
'istream',
'iterator',
'limits',
'list',
'locale',
'map',
'memory',
'mutex',
'new',
'numeric',
'ostream',
'queue',
'random',
'ratio',
'regex',
'scoped_allocator',
'set',
'sstream',
'stack',
'stdexcept',
'streambuf',
'string',
'strstream',
'system_error',
'thread',
'tuple',
'typeindex',
'typeinfo',
'type_traits',
'unordered_map',
'unordered_set',
'utility',
'valarray',
'vector',
# 17.6.1.2 C++14 headers
'shared_mutex',
# 17.6.1.2 C++17 headers
'any',
'charconv',
'codecvt',
'execution',
'filesystem',
'memory_resource',
'optional',
'string_view',
'variant',
# 17.6.1.2 C++ headers for C library facilities
'cassert',
'ccomplex',
'cctype',
'cerrno',
'cfenv',
'cfloat',
'cinttypes',
'ciso646',
'climits',
'clocale',
'cmath',
'csetjmp',
'csignal',
'cstdalign',
'cstdarg',
'cstdbool',
'cstddef',
'cstdint',
'cstdio',
'cstdlib',
'cstring',
'ctgmath',
'ctime',
'cuchar',
'cwchar',
'cwctype',
])
# C headers
_C_HEADERS = frozenset([
# System C headers
'assert.h',
'complex.h',
'ctype.h',
'errno.h',
'fenv.h',
'float.h',
'inttypes.h',
'iso646.h',
'limits.h',
'locale.h',
'math.h',
'setjmp.h',
'signal.h',
'stdalign.h',
'stdarg.h',
'stdatomic.h',
'stdbool.h',
'stddef.h',
'stdint.h',
'stdio.h',
'stdlib.h',
'stdnoreturn.h',
'string.h',
'tgmath.h',
'threads.h',
'time.h',
'uchar.h',
'wchar.h',
'wctype.h',
# additional POSIX C headers
'aio.h',
'arpa/inet.h',
'cpio.h',
'dirent.h',
'dlfcn.h',
'fcntl.h',
'fmtmsg.h',
'fnmatch.h',
'ftw.h',
'glob.h',
'grp.h',
'iconv.h',
'langinfo.h',
'libgen.h',
'monetary.h',
'mqueue.h',
'ndbm.h',
'net/if.h',
'netdb.h',
'netinet/in.h',
'netinet/tcp.h',
'nl_types.h',
'poll.h',
'pthread.h',
'pwd.h',
'regex.h',
'sched.h',
'search.h',
'semaphore.h',
'setjmp.h',
'signal.h',
'spawn.h',
'strings.h',
'stropts.h',
'syslog.h',
'tar.h',
'termios.h',
'trace.h',
'ulimit.h',
'unistd.h',
'utime.h',
'utmpx.h',
'wordexp.h',
# additional GNUlib headers
'a.out.h',
'aliases.h',
'alloca.h',
'ar.h',
'argp.h',
'argz.h',
'byteswap.h',
'crypt.h',
'endian.h',
'envz.h',
'err.h',
'error.h',
'execinfo.h',
'fpu_control.h',
'fstab.h',
'fts.h',
'getopt.h',
'gshadow.h',
'ieee754.h',
'ifaddrs.h',
'libintl.h',
'mcheck.h',
'mntent.h',
'obstack.h',
'paths.h',
'printf.h',
'pty.h',
'resolv.h',
'shadow.h',
'sysexits.h',
'ttyent.h',
# Additional linux glibc headers
'dlfcn.h',
'elf.h',
'features.h',
'gconv.h',
'gnu-versions.h',
'lastlog.h',
'libio.h',
'link.h',
'malloc.h',
'memory.h',
'netash/ash.h',
'netatalk/at.h',
'netax25/ax25.h',
'neteconet/ec.h',
'netipx/ipx.h',
'netiucv/iucv.h',
'netpacket/packet.h',
'netrom/netrom.h',
'netrose/rose.h',
'nfs/nfs.h',
'nl_types.h',
'nss.h',
're_comp.h',
'regexp.h',
'sched.h',
'sgtty.h',
'stab.h',
'stdc-predef.h',
'stdio_ext.h',
'syscall.h',
'termio.h',
'thread_db.h',
'ucontext.h',
'ustat.h',
'utmp.h',
'values.h',
'wait.h',
'xlocale.h',
# Hardware specific headers
'arm_neon.h',
'emmintrin.h',
'xmmintin.h',
])
# Folders of C libraries so commonly used in C++,
# that they have parity with standard C libraries.
C_STANDARD_HEADER_FOLDERS = frozenset([
# standard C library
"sys",
# glibc for linux
"arpa",
"asm-generic",
"bits",
"gnu",
"net",
"netinet",
"protocols",
"rpc",
"rpcsvc",
"scsi",
# linux kernel header
"drm",
"linux",
"misc",
"mtd",
"rdma",
"sound",
"video",
"xen",
])
# Type names
_TYPES = re.compile(
r'^(?:'
# [dcl.type.simple]
r'(char(16_t|32_t)?)|wchar_t|'
r'bool|short|int|long|signed|unsigned|float|double|'
# [support.types]
r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|'
# [cstdint.syn]
r'(u?int(_fast|_least)?(8|16|32|64)_t)|'
r'(u?int(max|ptr)_t)|'
r')$')
# These headers are excluded from [build/include] and [build/include_order]
# checks:
# - Anything not following google file name conventions (containing an
# uppercase character, such as Python.h or nsStringAPI.h, for example).
# - Lua headers.
_THIRD_PARTY_HEADERS_PATTERN = re.compile(
r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
# Pattern for matching FileInfo.BaseName() against test file name
_test_suffixes = ['_test', '_regtest', '_unittest']
_TEST_FILE_SUFFIX = '(' + '|'.join(_test_suffixes) + r')$'
# Pattern that matches only complete whitespace, possibly across multiple lines.
_EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL)
# Assertion macros. These are defined in base/logging.h and
# testing/base/public/gunit.h.
_CHECK_MACROS = [
'DCHECK', 'CHECK',
'EXPECT_TRUE', 'ASSERT_TRUE',
'EXPECT_FALSE', 'ASSERT_FALSE',
]
# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
_CHECK_REPLACEMENT = dict([(macro_var, {}) for macro_var in _CHECK_MACROS])
for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
('>=', 'GE'), ('>', 'GT'),
('<=', 'LE'), ('<', 'LT')]:
_CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
_CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
_CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
_CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
('>=', 'LT'), ('>', 'LE'),
('<=', 'GT'), ('<', 'GE')]:
_CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
_CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
# Alternative tokens and their replacements. For full list, see section 2.5
# Alternative tokens [lex.digraph] in the C++ standard.
#
# Digraphs (such as '%:') are not included here since it's a mess to
# match those on a word boundary.
_ALT_TOKEN_REPLACEMENT = {
'and': '&&',
'bitor': '|',
'or': '||',
'xor': '^',
'compl': '~',
'bitand': '&',
'and_eq': '&=',
'or_eq': '|=',
'xor_eq': '^=',
'not': '!',
'not_eq': '!='
}
# Compile regular expression that matches all the above keywords. The "[ =()]"
# bit is meant to avoid matching these keywords outside of boolean expressions.
#
# False positives include C-style multi-line comments and multi-line strings
# but those have always been troublesome for cpplint.
_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
# These constants define types of headers for use with
# _IncludeState.CheckNextIncludeOrder().
_C_SYS_HEADER = 1
_CPP_SYS_HEADER = 2
_OTHER_SYS_HEADER = 3
_LIKELY_MY_HEADER = 4
_POSSIBLE_MY_HEADER = 5
_OTHER_HEADER = 6
# These constants define the current inline assembly state
_NO_ASM = 0 # Outside of inline assembly block
_INSIDE_ASM = 1 # Inside inline assembly block
_END_ASM = 2 # Last line of inline assembly block
_BLOCK_ASM = 3 # The whole block is an inline assembly block
# Match start of assembly blocks
_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
r'(?:\s+(volatile|__volatile__))?'
r'\s*[{(]')
# Match strings that indicate we're working on a C (not C++) file.
_SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|'
r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))')
# Match string that indicates we're working on a Linux Kernel file.
_SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)')
# Commands for sed to fix the problem
_SED_FIXUPS = {
'Remove spaces around =': r's/ = /=/',
'Remove spaces around !=': r's/ != /!=/',
'Remove space before ( in if (': r's/if (/if(/',
'Remove space before ( in for (': r's/for (/for(/',
'Remove space before ( in while (': r's/while (/while(/',
'Remove space before ( in switch (': r's/switch (/switch(/',
'Should have a space between // and comment': r's/\/\//\/\/ /',
'Missing space before {': r's/\([^ ]\){/\1 {/',
'Tab found, replace by spaces': r's/\t/ /g',
'Line ends in whitespace. Consider deleting these extra spaces.': r's/\s*$//',
'You don\'t need a ; after a }': r's/};/}/',
'Missing space after ,': r's/,\([^ ]\)/, \1/g',
}
_regexp_compile_cache = {}
# {str, set(int)}: a map from error categories to sets of linenumbers
# on which those errors are expected and should be suppressed.
_error_suppressions = {}
# The root directory used for deriving header guard CPP variable.
# This is set by --root flag.
_root = None
_root_debug = False
# The top level repository directory. If set, _root is calculated relative to
# this directory instead of the directory containing version control artifacts.
# This is set by the --repository flag.
_repository = None
# Files to exclude from linting. This is set by the --exclude flag.
_excludes = None
# Whether to supress all PrintInfo messages, UNRELATED to --quiet flag
_quiet = False
# The allowed line length of files.
# This is set by --linelength flag.
_line_length = 80
# This allows to use different include order rule than default
_include_order = "default"
try:
unicode
except NameError:
# -- pylint: disable=redefined-builtin
basestring = unicode = str
try:
long
except NameError:
# -- pylint: disable=redefined-builtin
long = int
if sys.version_info < (3,):
# -- pylint: disable=no-member
# BINARY_TYPE = str
itervalues = dict.itervalues
iteritems = dict.iteritems
else:
# BINARY_TYPE = bytes
itervalues = dict.values
iteritems = dict.items
def unicode_escape_decode(x):
if sys.version_info < (3,):
return codecs.unicode_escape_decode(x)[0]
else:
return x
# Treat all headers starting with 'h' equally: .h, .hpp, .hxx etc.
# This is set by --headers flag.
_hpp_headers = set([])
# {str, bool}: a map from error categories to booleans which indicate if the
# category should be suppressed for every line.
_global_error_suppressions = {}
def ProcessHppHeadersOption(val):
global _hpp_headers
try:
_hpp_headers = {ext.strip() for ext in val.split(',')}
except ValueError:
PrintUsage('Header extensions must be comma separated list.')
def ProcessIncludeOrderOption(val):
if val is None or val == "default":
pass
elif val == "standardcfirst":
global _include_order
_include_order = val
else:
PrintUsage('Invalid includeorder value %s. Expected default|standardcfirst')
def IsHeaderExtension(file_extension):
return file_extension in GetHeaderExtensions()
def GetHeaderExtensions():
if _hpp_headers:
return _hpp_headers
if _valid_extensions:
return {h for h in _valid_extensions if 'h' in h}
return set(['h', 'hh', 'hpp', 'hxx', 'h++', 'cuh'])
# The allowed extensions for file names
# This is set by --extensions flag
def GetAllExtensions():
return GetHeaderExtensions().union(_valid_extensions or set(
['c', 'cc', 'cpp', 'cxx', 'c++', 'cu']))
def ProcessExtensionsOption(val):
global _valid_extensions
try:
extensions = [ext.strip() for ext in val.split(',')]
_valid_extensions = set(extensions)
except ValueError:
PrintUsage('Extensions should be a comma-separated list of values;'
'for example: extensions=hpp,cpp\n'
'This could not be parsed: "%s"' % (val,))
def GetNonHeaderExtensions():
return GetAllExtensions().difference(GetHeaderExtensions())
def ParseNolintSuppressions(filename, raw_line, linenum, error):
"""Updates the global list of line error-suppressions.
Parses any NOLINT comments on the current line, updating the global
error_suppressions store. Reports an error if the NOLINT comment
was malformed.
Args:
filename: str, the name of the input file.
raw_line: str, the line of input text, with comments.
linenum: int, the number of the current line.
error: function, an error handler.
"""
matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
if matched:
if matched.group(1):
suppressed_line = linenum + 1
else:
suppressed_line = linenum
category = matched.group(2)
if category in (None, '(*)'): # => "suppress all"
_error_suppressions.setdefault(None, set()).add(suppressed_line)
else:
if category.startswith('(') and category.endswith(')'):
category = category[1:-1]
if category in _ERROR_CATEGORIES:
_error_suppressions.setdefault(category, set()).add(suppressed_line)
elif category not in _LEGACY_ERROR_CATEGORIES:
error(filename, linenum, 'readability/nolint', 5,
'Unknown NOLINT error category: %s' % category)
def ProcessGlobalSuppresions(lines):
"""Updates the list of global error suppressions.
Parses any lint directives in the file that have global effect.
Args:
lines: An array of strings, each representing a line of the file, with the
last element being empty if the file is terminated with a newline.
"""
for line in lines:
if _SEARCH_C_FILE.search(line):
for category in _DEFAULT_C_SUPPRESSED_CATEGORIES:
_global_error_suppressions[category] = True
if _SEARCH_KERNEL_FILE.search(line):
for category in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES:
_global_error_suppressions[category] = True
def ResetNolintSuppressions():
"""Resets the set of NOLINT suppressions to empty."""
_error_suppressions.clear()
_global_error_suppressions.clear()
def IsErrorSuppressedByNolint(category, linenum):
"""Returns true if the specified error category is suppressed on this line.
Consults the global error_suppressions map populated by
ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions.
Args:
category: str, the category of the error.
linenum: int, the current line number.
Returns:
bool, True iff the error should be suppressed due to a NOLINT comment or
global suppression.
"""
return (_global_error_suppressions.get(category, False) or
linenum in _error_suppressions.get(category, set()) or
linenum in _error_suppressions.get(None, set()))
def Match(pattern, s):
"""Matches the string with the pattern, caching the compiled regexp."""
# The regexp compilation caching is inlined in both Match and Search for
# performance reasons; factoring it out into a separate function turns out
# to be noticeably expensive.
if pattern not in _regexp_compile_cache:
_regexp_compile_cache[pattern] = sre_compile.compile(pattern)
return _regexp_compile_cache[pattern].match(s)
def ReplaceAll(pattern, rep, s):
"""Replaces instances of pattern in a string with a replacement.
The compiled regex is kept in a cache shared by Match and Search.
Args:
pattern: regex pattern
rep: replacement text
s: search string
Returns:
string with replacements made (or original string if no replacements)
"""
if pattern not in _regexp_compile_cache:
_regexp_compile_cache[pattern] = sre_compile.compile(pattern)
return _regexp_compile_cache[pattern].sub(rep, s)
def Search(pattern, s):
"""Searches the string for the pattern, caching the compiled regexp."""
if pattern not in _regexp_compile_cache:
_regexp_compile_cache[pattern] = sre_compile.compile(pattern)
return _regexp_compile_cache[pattern].search(s)
def _IsSourceExtension(s):
"""File extension (excluding dot) matches a source file extension."""
return s in GetNonHeaderExtensions()
class _IncludeState(object):
"""Tracks line numbers for includes, and the order in which includes appear.
include_list contains list of lists of (header, line number) pairs.
It's a lists of lists rather than just one flat list to make it
easier to update across preprocessor boundaries.
Call CheckNextIncludeOrder() once for each header in the file, passing
in the type constants defined above. Calls in an illegal order will
raise an _IncludeError with an appropriate error message.
"""
# self._section will move monotonically through this set. If it ever
# needs to move backwards, CheckNextIncludeOrder will raise an error.
_INITIAL_SECTION = 0
_MY_H_SECTION = 1
_C_SECTION = 2
_CPP_SECTION = 3
_OTHER_SYS_SECTION = 4
_OTHER_H_SECTION = 5
_TYPE_NAMES = {
_C_SYS_HEADER: 'C system header',
_CPP_SYS_HEADER: 'C++ system header',
_OTHER_SYS_HEADER: 'other system header',
_LIKELY_MY_HEADER: 'header this file implements',
_POSSIBLE_MY_HEADER: 'header this file may implement',
_OTHER_HEADER: 'other header',
}
_SECTION_NAMES = {
_INITIAL_SECTION: "... nothing. (This can't be an error.)",
_MY_H_SECTION: 'a header this file implements',
_C_SECTION: 'C system header',
_CPP_SECTION: 'C++ system header',
_OTHER_SYS_SECTION: 'other system header',
_OTHER_H_SECTION: 'other header',
}
def __init__(self):
self.include_list = [[]]
self._section = None
self._last_header = None
self.ResetSection('')
def FindHeader(self, header):
"""Check if a header has already been included.
Args:
header: header to check.
Returns:
Line number of previous occurrence, or -1 if the header has not
been seen before.
"""
for section_list in self.include_list:
for f in section_list:
if f[0] == header:
return f[1]
return -1
def ResetSection(self, directive):
"""Reset section checking for preprocessor directive.
Args:
directive: preprocessor directive (e.g. "if", "else").
"""
# The name of the current section.
self._section = self._INITIAL_SECTION
# The path of last found header.
self._last_header = ''
# Update list of includes. Note that we never pop from the
# include list.
if directive in ('if', 'ifdef', 'ifndef'):
self.include_list.append([])
elif directive in ('else', 'elif'):
self.include_list[-1] = []
def SetLastHeader(self, header_path):
self._last_header = header_path
def CanonicalizeAlphabeticalOrder(self, header_path):
"""Returns a path canonicalized for alphabetical comparison.
- replaces "-" with "_" so they both cmp the same.
- removes '-inl' since we don't require them to be after the main header.
- lowercase everything, just in case.
Args:
header_path: Path to be canonicalized.
Returns:
Canonicalized path.
"""
return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
"""Check if a header is in alphabetical order with the previous header.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
header_path: Canonicalized header to be checked.
Returns:
Returns true if the header is in alphabetical order.
"""
# If previous section is different from current section, _last_header will
# be reset to empty string, so it's always less than current header.
#
# If previous line was a blank line, assume that the headers are
# intentionally sorted the way they are.
if (self._last_header > header_path and
Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
return False
return True
def CheckNextIncludeOrder(self, header_type):
"""Returns a non-empty error message if the next header is out of order.
This function also updates the internal state to be ready to check
the next include.
Args:
header_type: One of the _XXX_HEADER constants defined above.
Returns:
The empty string if the header is in the right order, or an
error message describing what's wrong.
"""
error_message = ('Found %s after %s' %
(self._TYPE_NAMES[header_type],
self._SECTION_NAMES[self._section]))
last_section = self._section
if header_type == _C_SYS_HEADER:
if self._section <= self._C_SECTION:
self._section = self._C_SECTION
else:
self._last_header = ''
return error_message
elif header_type == _CPP_SYS_HEADER:
if self._section <= self._CPP_SECTION:
self._section = self._CPP_SECTION
else:
self._last_header = ''
return error_message
elif header_type == _OTHER_SYS_HEADER:
if self._section <= self._OTHER_SYS_SECTION:
self._section = self._OTHER_SYS_SECTION
else:
self._last_header = ''
return error_message
elif header_type == _LIKELY_MY_HEADER:
if self._section <= self._MY_H_SECTION:
self._section = self._MY_H_SECTION
else:
self._section = self._OTHER_H_SECTION
elif header_type == _POSSIBLE_MY_HEADER:
if self._section <= self._MY_H_SECTION:
self._section = self._MY_H_SECTION
else:
# This will always be the fallback because we're not sure
# enough that the header is associated with this file.
self._section = self._OTHER_H_SECTION
else:
assert header_type == _OTHER_HEADER
self._section = self._OTHER_H_SECTION
if last_section != self._section:
self._last_header = ''
return ''
class _CppLintState(object):
"""Maintains module-wide state.."""
def __init__(self):
self.verbose_level = 1 # global setting.
self.error_count = 0 # global count of reported errors
# filters to apply when emitting error messages
self.filters = _DEFAULT_FILTERS[:]
# backup of filter list. Used to restore the state after each file.
self._filters_backup = self.filters[:]
self.counting = 'total' # In what way are we counting errors?
self.errors_by_category = {} # string to int dict storing error counts
self.quiet = False # Suppress non-error messagess?
# output format:
# "emacs" - format that emacs can parse (default)
# "eclipse" - format that eclipse can parse
# "vs7" - format that Microsoft Visual Studio 7 can parse
# "junit" - format that Jenkins, Bamboo, etc can parse
# "sed" - returns a gnu sed command to fix the problem
# "gsed" - like sed, but names the command gsed, e.g. for macOS homebrew users
self.output_format = 'emacs'
# For JUnit output, save errors and failures until the end so that they
# can be written into the XML
self._junit_errors = []
self._junit_failures = []
def SetOutputFormat(self, output_format):
"""Sets the output format for errors."""
self.output_format = output_format
def SetQuiet(self, quiet):
"""Sets the module's quiet settings, and returns the previous setting."""
last_quiet = self.quiet
self.quiet = quiet
return last_quiet
def SetVerboseLevel(self, level):
"""Sets the module's verbosity, and returns the previous setting."""
last_verbose_level = self.verbose_level
self.verbose_level = level
return last_verbose_level
def SetCountingStyle(self, counting_style):
"""Sets the module's counting options."""
self.counting = counting_style
def SetFilters(self, filters):
"""Sets the error-message filters.
These filters are applied when deciding whether to emit a given
error message.
Args:
filters: A string of comma-separated filters (eg "+whitespace/indent").
Each filter should start with + or -; else we die.
Raises:
ValueError: The comma-separated filters did not all start with '+' or '-'.
E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
"""
# Default filters always have less priority than the flag ones.
self.filters = _DEFAULT_FILTERS[:]
self.AddFilters(filters)
def AddFilters(self, filters):
""" Adds more filters to the existing list of error-message filters. """
for filt in filters.split(','):
clean_filt = filt.strip()
if clean_filt:
self.filters.append(clean_filt)
for filt in self.filters:
if not (filt.startswith('+') or filt.startswith('-')):
raise ValueError('Every filter in --filters must start with + or -'
' (%s does not)' % filt)
def BackupFilters(self):
""" Saves the current filter list to backup storage."""
self._filters_backup = self.filters[:]
def RestoreFilters(self):
""" Restores filters previously backed up."""
self.filters = self._filters_backup[:]
def ResetErrorCounts(self):
"""Sets the module's error statistic back to zero."""
self.error_count = 0
self.errors_by_category = {}
def IncrementErrorCount(self, category):
"""Bumps the module's error statistic."""
self.error_count += 1
if self.counting in ('toplevel', 'detailed'):
if self.counting != 'detailed':
category = category.split('/')[0]
if category not in self.errors_by_category:
self.errors_by_category[category] = 0
self.errors_by_category[category] += 1
def PrintErrorCounts(self):
"""Print a summary of errors by category, and the total."""
for category, count in sorted(iteritems(self.errors_by_category)):
self.PrintInfo('Category \'%s\' errors found: %d\n' %
(category, count))
if self.error_count > 0:
self.PrintInfo('Total errors found: %d\n' % self.error_count)
def PrintInfo(self, message):
# _quiet does not represent --quiet flag.
# Hide infos from stdout to keep stdout pure for machine consumption
if not _quiet and self.output_format not in _MACHINE_OUTPUTS:
sys.stdout.write(message)
def PrintError(self, message):
if self.output_format == 'junit':
self._junit_errors.append(message)
else:
sys.stderr.write(message)
def AddJUnitFailure(self, filename, linenum, message, category, confidence):
self._junit_failures.append((filename, linenum, message, category,
confidence))
def FormatJUnitXML(self):
num_errors = len(self._junit_errors)
num_failures = len(self._junit_failures)
testsuite = xml.etree.ElementTree.Element('testsuite')
testsuite.attrib['errors'] = str(num_errors)
testsuite.attrib['failures'] = str(num_failures)
testsuite.attrib['name'] = 'cpplint'
if num_errors == 0 and num_failures == 0:
testsuite.attrib['tests'] = str(1)
xml.etree.ElementTree.SubElement(testsuite, 'testcase', name='passed')
else:
testsuite.attrib['tests'] = str(num_errors + num_failures)
if num_errors > 0:
testcase = xml.etree.ElementTree.SubElement(testsuite, 'testcase')
testcase.attrib['name'] = 'errors'
error = xml.etree.ElementTree.SubElement(testcase, 'error')
error.text = '\n'.join(self._junit_errors)
if num_failures > 0:
# Group failures by file
failed_file_order = []
failures_by_file = {}
for failure in self._junit_failures:
failed_file = failure[0]
if failed_file not in failed_file_order:
failed_file_order.append(failed_file)
failures_by_file[failed_file] = []
failures_by_file[failed_file].append(failure)
# Create a testcase for each file
for failed_file in failed_file_order:
failures = failures_by_file[failed_file]
testcase = xml.etree.ElementTree.SubElement(testsuite, 'testcase')
testcase.attrib['name'] = failed_file
failure = xml.etree.ElementTree.SubElement(testcase, 'failure')
template = '{0}: {1} [{2}] [{3}]'
texts = [template.format(f[1], f[2], f[3], f[4]) for f in failures]
failure.text = '\n'.join(texts)
xml_decl = '\n'
return xml_decl + xml.etree.ElementTree.tostring(testsuite, 'utf-8').decode('utf-8')
_cpplint_state = _CppLintState()
def _OutputFormat():
"""Gets the module's output format."""
return _cpplint_state.output_format
def _SetOutputFormat(output_format):
"""Sets the module's output format."""
_cpplint_state.SetOutputFormat(output_format)
def _Quiet():
"""Return's the module's quiet setting."""
return _cpplint_state.quiet
def _SetQuiet(quiet):
"""Set the module's quiet status, and return previous setting."""
return _cpplint_state.SetQuiet(quiet)
def _VerboseLevel():
"""Returns the module's verbosity setting."""
return _cpplint_state.verbose_level
def _SetVerboseLevel(level):
"""Sets the module's verbosity, and returns the previous setting."""
return _cpplint_state.SetVerboseLevel(level)
def _SetCountingStyle(level):
"""Sets the module's counting options."""
_cpplint_state.SetCountingStyle(level)
def _Filters():
"""Returns the module's list of output filters, as a list."""
return _cpplint_state.filters
def _SetFilters(filters):
"""Sets the module's error-message filters.
These filters are applied when deciding whether to emit a given
error message.
Args:
filters: A string of comma-separated filters (eg "whitespace/indent").
Each filter should start with + or -; else we die.
"""
_cpplint_state.SetFilters(filters)
def _AddFilters(filters):
"""Adds more filter overrides.
Unlike _SetFilters, this function does not reset the current list of filters
available.
Args:
filters: A string of comma-separated filters (eg "whitespace/indent").
Each filter should start with + or -; else we die.
"""
_cpplint_state.AddFilters(filters)
def _BackupFilters():
""" Saves the current filter list to backup storage."""
_cpplint_state.BackupFilters()
def _RestoreFilters():
""" Restores filters previously backed up."""
_cpplint_state.RestoreFilters()
class _FunctionState(object):
"""Tracks current function name and the number of lines in its body."""
_NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
_TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
def __init__(self):
self.in_a_function = False
self.lines_in_function = 0
self.current_function = ''
def Begin(self, function_name):
"""Start analyzing function body.
Args:
function_name: The name of the function being tracked.
"""
self.in_a_function = True
self.lines_in_function = 0
self.current_function = function_name
def Count(self):
"""Count line in current function body."""
if self.in_a_function:
self.lines_in_function += 1
def Check(self, error, filename, linenum):
"""Report if too many lines in function body.
Args:
error: The function to call with any errors found.
filename: The name of the current file.
linenum: The number of the line to check.
"""
if not self.in_a_function:
return
if Match(r'T(EST|est)', self.current_function):
base_trigger = self._TEST_TRIGGER
else:
base_trigger = self._NORMAL_TRIGGER
trigger = base_trigger * 2**_VerboseLevel()
if self.lines_in_function > trigger:
error_level = int(math.log(self.lines_in_function / base_trigger, 2))
# 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
if error_level > 5:
error_level = 5
error(filename, linenum, 'readability/fn_size', error_level,
'Small and focused functions are preferred:'
' %s has %d non-comment lines'
' (error triggered by exceeding %d lines).' % (
self.current_function, self.lines_in_function, trigger))
def End(self):
"""Stop analyzing function body."""
self.in_a_function = False
class _IncludeError(Exception):
"""Indicates a problem with the include order in a file."""
pass
class FileInfo(object):
"""Provides utility functions for filenames.
FileInfo provides easy access to the components of a file's path
relative to the project root.
"""
def __init__(self, filename):
self._filename = filename
def FullName(self):
"""Make Windows paths like Unix."""
return os.path.abspath(self._filename).replace('\\', '/')
def RepositoryName(self):
r"""FullName after removing the local path to the repository.
If we have a real absolute path name here we can try to do something smart:
detecting the root of the checkout and truncating /path/to/checkout from
the name so that we get header guards that don't include things like
"C:\\Documents and Settings\\..." or "/home/username/..." in them and thus
people on different computers who have checked the source out to different
locations won't see bogus errors.
"""
fullname = self.FullName()
if os.path.exists(fullname):
project_dir = os.path.dirname(fullname)
# If the user specified a repository path, it exists, and the file is
# contained in it, use the specified repository path
if _repository:
repo = FileInfo(_repository).FullName()
root_dir = project_dir
while os.path.exists(root_dir):
# allow case insensitive compare on Windows
if os.path.normcase(root_dir) == os.path.normcase(repo):
return os.path.relpath(fullname, root_dir).replace('\\', '/')
one_up_dir = os.path.dirname(root_dir)
if one_up_dir == root_dir:
break
root_dir = one_up_dir
if os.path.exists(os.path.join(project_dir, ".svn")):
# If there's a .svn file in the current directory, we recursively look
# up the directory tree for the top of the SVN checkout
root_dir = project_dir
one_up_dir = os.path.dirname(root_dir)
while os.path.exists(os.path.join(one_up_dir, ".svn")):
root_dir = os.path.dirname(root_dir)
one_up_dir = os.path.dirname(one_up_dir)
prefix = os.path.commonprefix([root_dir, project_dir])
return fullname[len(prefix) + 1:]
# Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
# searching up from the current path.
root_dir = current_dir = os.path.dirname(fullname)
while current_dir != os.path.dirname(current_dir):
if (os.path.exists(os.path.join(current_dir, ".git")) or
os.path.exists(os.path.join(current_dir, ".hg")) or
os.path.exists(os.path.join(current_dir, ".svn"))):
root_dir = current_dir
current_dir = os.path.dirname(current_dir)
if (os.path.exists(os.path.join(root_dir, ".git")) or
os.path.exists(os.path.join(root_dir, ".hg")) or
os.path.exists(os.path.join(root_dir, ".svn"))):
prefix = os.path.commonprefix([root_dir, project_dir])
return fullname[len(prefix) + 1:]
# Don't know what to do; header guard warnings may be wrong...
return fullname
def Split(self):
"""Splits the file into the directory, basename, and extension.
For 'chrome/browser/browser.cc', Split() would
return ('chrome/browser', 'browser', '.cc')
Returns:
A tuple of (directory, basename, extension).
"""
googlename = self.RepositoryName()
project, rest = os.path.split(googlename)
return (project,) + os.path.splitext(rest)
def BaseName(self):
"""File base name - text after the final slash, before the final period."""
return self.Split()[1]
def Extension(self):
"""File extension - text following the final period, includes that period."""
return self.Split()[2]
def NoExtension(self):
"""File has no source file extension."""
return '/'.join(self.Split()[0:2])
def IsSource(self):
"""File has a source file extension."""
return _IsSourceExtension(self.Extension()[1:])
def _ShouldPrintError(category, confidence, linenum):
"""If confidence >= verbose, category passes filter and is not suppressed."""
# There are three ways we might decide not to print an error message:
# a "NOLINT(category)" comment appears in the source,
# the verbosity level isn't high enough, or the filters filter it out.
if IsErrorSuppressedByNolint(category, linenum):
return False
if confidence < _cpplint_state.verbose_level:
return False
is_filtered = False
for one_filter in _Filters():
if one_filter.startswith('-'):
if category.startswith(one_filter[1:]):
is_filtered = True
elif one_filter.startswith('+'):
if category.startswith(one_filter[1:]):
is_filtered = False
else:
assert False # should have been checked for in SetFilter.
if is_filtered:
return False
return True
def Error(filename, linenum, category, confidence, message):
"""Logs the fact we've found a lint error.
We log where the error was found, and also our confidence in the error,
that is, how certain we are this is a legitimate style regression, and
not a misidentification or a use that's sometimes justified.
False positives can be suppressed by the use of
"cpplint(category)" comments on the offending line. These are
parsed into _error_suppressions.
Args:
filename: The name of the file containing the error.
linenum: The number of the line containing the error.
category: A string used to describe the "category" this bug
falls under: "whitespace", say, or "runtime". Categories
may have a hierarchy separated by slashes: "whitespace/indent".
confidence: A number from 1-5 representing a confidence score for
the error, with 5 meaning that we are certain of the problem,
and 1 meaning that it could be a legitimate construct.
message: The error message.
"""
if _ShouldPrintError(category, confidence, linenum):
_cpplint_state.IncrementErrorCount(category)
if _cpplint_state.output_format == 'vs7':
_cpplint_state.PrintError('%s(%s): error cpplint: [%s] %s [%d]\n' % (
filename, linenum, category, message, confidence))
elif _cpplint_state.output_format == 'eclipse':
sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % (
filename, linenum, message, category, confidence))
elif _cpplint_state.output_format == 'junit':
_cpplint_state.AddJUnitFailure(filename, linenum, message, category,
confidence)
elif _cpplint_state.output_format in ['sed', 'gsed']:
if message in _SED_FIXUPS:
sys.stdout.write(_cpplint_state.output_format + " -i '%s%s' %s # %s [%s] [%d]\n" % (
linenum, _SED_FIXUPS[message], filename, message, category, confidence))
else:
sys.stderr.write('# %s:%s: "%s" [%s] [%d]\n' % (
filename, linenum, message, category, confidence))
else:
final_message = '%s:%s: %s [%s] [%d]\n' % (
filename, linenum, message, category, confidence)
sys.stderr.write(final_message)
# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
# Match a single C style comment on the same line.
_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
# Matches multi-line C style comments.
# This RE is a little bit more complicated than one might expect, because we
# have to take care of space removals tools so we can handle comments inside
# statements better.
# The current rule is: We only clear spaces from both sides when we're at the
# end of the line. Otherwise, we try to remove spaces from the right side,
# if this doesn't work we try on left side but only if there's a non-character
# on the right.
_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
_RE_PATTERN_C_COMMENTS + r'\s+|' +
r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
_RE_PATTERN_C_COMMENTS + r')')
def IsCppString(line):
"""Does line terminate so, that the next symbol is in string constant.
This function does not consider single-line nor multi-line comments.
Args:
line: is a partial line of code starting from the 0..n.
Returns:
True, if next character appended to 'line' is inside a
string constant.
"""
line = line.replace(r'\\', 'XX') # after this, \\" does not match to \"
return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
def CleanseRawStrings(raw_lines):
"""Removes C++11 raw strings from lines.
Before:
static const char kData[] = R"(
multi-line string
)";
After:
static const char kData[] = ""
(replaced by blank line)
"";
Args:
raw_lines: list of raw lines.
Returns:
list of lines with C++11 raw strings replaced by empty strings.
"""
delimiter = None
lines_without_raw_strings = []
for line in raw_lines:
if delimiter:
# Inside a raw string, look for the end
end = line.find(delimiter)
if end >= 0:
# Found the end of the string, match leading space for this
# line and resume copying the original lines, and also insert
# a "" on the last line.
leading_space = Match(r'^(\s*)\S', line)
line = leading_space.group(1) + '""' + line[end + len(delimiter):]
delimiter = None
else:
# Haven't found the end yet, append a blank line.
line = '""'
# Look for beginning of a raw string, and replace them with
# empty strings. This is done in a loop to handle multiple raw
# strings on the same line.
while delimiter is None:
# Look for beginning of a raw string.
# See 2.14.15 [lex.string] for syntax.
#
# Once we have matched a raw string, we check the prefix of the
# line to make sure that the line is not part of a single line
# comment. It's done this way because we remove raw strings
# before removing comments as opposed to removing comments
# before removing raw strings. This is because there are some
# cpplint checks that requires the comments to be preserved, but
# we don't want to check comments that are inside raw strings.
matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
if (matched and
not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
matched.group(1))):
delimiter = ')' + matched.group(2) + '"'
end = matched.group(3).find(delimiter)
if end >= 0:
# Raw string ended on same line
line = (matched.group(1) + '""' +
matched.group(3)[end + len(delimiter):])
delimiter = None
else:
# Start of a multi-line raw string
line = matched.group(1) + '""'
else:
break
lines_without_raw_strings.append(line)
# TODO(unknown): if delimiter is not None here, we might want to
# emit a warning for unterminated string.
return lines_without_raw_strings
def FindNextMultiLineCommentStart(lines, lineix):
"""Find the beginning marker for a multiline comment."""
while lineix < len(lines):
if lines[lineix].strip().startswith('/*'):
# Only return this marker if the comment goes beyond this line
if lines[lineix].strip().find('*/', 2) < 0:
return lineix
lineix += 1
return len(lines)
def FindNextMultiLineCommentEnd(lines, lineix):
"""We are inside a comment, find the end marker."""
while lineix < len(lines):
if lines[lineix].strip().endswith('*/'):
return lineix
lineix += 1
return len(lines)
def RemoveMultiLineCommentsFromRange(lines, begin, end):
"""Clears a range of lines for multi-line comments."""
# Having // comments makes the lines non-empty, so we will not get
# unnecessary blank line warnings later in the code.
for i in range(begin, end):
lines[i] = '/**/'
def RemoveMultiLineComments(filename, lines, error):
"""Removes multiline (c-style) comments from lines."""
lineix = 0
while lineix < len(lines):
lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
if lineix_begin >= len(lines):
return
lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
if lineix_end >= len(lines):
error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
'Could not find end of multi-line comment')
return
RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
lineix = lineix_end + 1
def CleanseComments(line):
"""Removes //-comments and single-line C-style /* */ comments.
Args:
line: A line of C++ source.
Returns:
The line with single-line comments removed.
"""
commentpos = line.find('//')
if commentpos != -1 and not IsCppString(line[:commentpos]):
line = line[:commentpos].rstrip()
# get rid of /* ... */
return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
class CleansedLines(object):
"""Holds 4 copies of all lines with different preprocessing applied to them.
1) elided member contains lines without strings and comments.
2) lines member contains lines without comments.
3) raw_lines member contains all the lines without processing.
4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
strings removed.
All these members are of , and of the same length.
"""
def __init__(self, lines):
self.elided = []
self.lines = []
self.raw_lines = lines
self.num_lines = len(lines)
self.lines_without_raw_strings = CleanseRawStrings(lines)
for linenum in range(len(self.lines_without_raw_strings)):
self.lines.append(CleanseComments(
self.lines_without_raw_strings[linenum]))
elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
self.elided.append(CleanseComments(elided))
def NumLines(self):
"""Returns the number of lines represented."""
return self.num_lines
@staticmethod
def _CollapseStrings(elided):
"""Collapses strings and chars on a line to simple "" or '' blocks.
We nix strings first so we're not fooled by text like '"http://"'
Args:
elided: The line being processed.
Returns:
The line with collapsed strings.
"""
if _RE_PATTERN_INCLUDE.match(elided):
return elided
# Remove escaped characters first to make quote/single quote collapsing
# basic. Things that look like escaped characters shouldn't occur
# outside of strings and chars.
elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
# Replace quoted strings and digit separators. Both single quotes
# and double quotes are processed in the same loop, otherwise
# nested quotes wouldn't work.
collapsed = ''
while True:
# Find the first quote character
match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
if not match:
collapsed += elided
break
head, quote, tail = match.groups()
if quote == '"':
# Collapse double quoted strings
second_quote = tail.find('"')
if second_quote >= 0:
collapsed += head + '""'
elided = tail[second_quote + 1:]
else:
# Unmatched double quote, don't bother processing the rest
# of the line since this is probably a multiline string.
collapsed += elided
break
else:
# Found single quote, check nearby text to eliminate digit separators.
#
# There is no special handling for floating point here, because
# the integer/fractional/exponent parts would all be parsed
# correctly as long as there are digits on both sides of the
# separator. So we are fine as long as we don't see something
# like "0.'3" (gcc 4.9.0 will not allow this literal).
if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
collapsed += head + match_literal.group(1).replace("'", '')
elided = match_literal.group(2)
else:
second_quote = tail.find('\'')
if second_quote >= 0:
collapsed += head + "''"
elided = tail[second_quote + 1:]
else:
# Unmatched single quote
collapsed += elided
break
return collapsed
def FindEndOfExpressionInLine(line, startpos, stack):
"""Find the position just after the end of current parenthesized expression.
Args:
line: a CleansedLines line.
startpos: start searching at this position.
stack: nesting stack at startpos.
Returns:
On finding matching end: (index just after matching end, None)
On finding an unclosed expression: (-1, None)
Otherwise: (-1, new stack at end of this line)
"""
for i in xrange(startpos, len(line)):
char = line[i]
if char in '([{':
# Found start of parenthesized expression, push to expression stack
stack.append(char)
elif char == '<':
# Found potential start of template argument list
if i > 0 and line[i - 1] == '<':
# Left shift operator
if stack and stack[-1] == '<':
stack.pop()
if not stack:
return (-1, None)
elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
# operator<, don't add to stack
continue
else:
# Tentative start of template argument list
stack.append('<')
elif char in ')]}':
# Found end of parenthesized expression.
#
# If we are currently expecting a matching '>', the pending '<'
# must have been an operator. Remove them from expression stack.
while stack and stack[-1] == '<':
stack.pop()
if not stack:
return (-1, None)
if ((stack[-1] == '(' and char == ')') or
(stack[-1] == '[' and char == ']') or
(stack[-1] == '{' and char == '}')):
stack.pop()
if not stack:
return (i + 1, None)
else:
# Mismatched parentheses
return (-1, None)
elif char == '>':
# Found potential end of template argument list.
# Ignore "->" and operator functions
if (i > 0 and
(line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
continue
# Pop the stack if there is a matching '<'. Otherwise, ignore
# this '>' since it must be an operator.
if stack:
if stack[-1] == '<':
stack.pop()
if not stack:
return (i + 1, None)
elif char == ';':
# Found something that look like end of statements. If we are currently
# expecting a '>', the matching '<' must have been an operator, since
# template argument list should not contain statements.
while stack and stack[-1] == '<':
stack.pop()
if not stack:
return (-1, None)
# Did not find end of expression or unbalanced parentheses on this line
return (-1, stack)
def CloseExpression(clean_lines, linenum, pos):
"""If input points to ( or { or [ or <, finds the position that closes it.
If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
linenum/pos that correspond to the closing of the expression.
TODO(unknown): cpplint spends a fair bit of time matching parentheses.
Ideally we would want to index all opening and closing parentheses once
and have CloseExpression be just a simple lookup, but due to preprocessor
tricks, this is not so easy.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
pos: A position on the line.
Returns:
A tuple (line, linenum, pos) pointer *past* the closing brace, or
(line, len(lines), -1) if we never find a close. Note we ignore
strings and comments when matching; and the line we return is the
'cleansed' line at linenum.
"""
line = clean_lines.elided[linenum]
if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
return (line, clean_lines.NumLines(), -1)
# Check first line
(end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
if end_pos > -1:
return (line, linenum, end_pos)
# Continue scanning forward
while stack and linenum < clean_lines.NumLines() - 1:
linenum += 1
line = clean_lines.elided[linenum]
(end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
if end_pos > -1:
return (line, linenum, end_pos)
# Did not find end of expression before end of file, give up
return (line, clean_lines.NumLines(), -1)
def FindStartOfExpressionInLine(line, endpos, stack):
"""Find position at the matching start of current expression.
This is almost the reverse of FindEndOfExpressionInLine, but note
that the input position and returned position differs by 1.
Args:
line: a CleansedLines line.
endpos: start searching at this position.
stack: nesting stack at endpos.
Returns:
On finding matching start: (index at matching start, None)
On finding an unclosed expression: (-1, None)
Otherwise: (-1, new stack at beginning of this line)
"""
i = endpos
while i >= 0:
char = line[i]
if char in ')]}':
# Found end of expression, push to expression stack
stack.append(char)
elif char == '>':
# Found potential end of template argument list.
#
# Ignore it if it's a "->" or ">=" or "operator>"
if (i > 0 and
(line[i - 1] == '-' or
Match(r'\s>=\s', line[i - 1:]) or
Search(r'\boperator\s*$', line[0:i]))):
i -= 1
else:
stack.append('>')
elif char == '<':
# Found potential start of template argument list
if i > 0 and line[i - 1] == '<':
# Left shift operator
i -= 1
else:
# If there is a matching '>', we can pop the expression stack.
# Otherwise, ignore this '<' since it must be an operator.
if stack and stack[-1] == '>':
stack.pop()
if not stack:
return (i, None)
elif char in '([{':
# Found start of expression.
#
# If there are any unmatched '>' on the stack, they must be
# operators. Remove those.
while stack and stack[-1] == '>':
stack.pop()
if not stack:
return (-1, None)
if ((char == '(' and stack[-1] == ')') or
(char == '[' and stack[-1] == ']') or
(char == '{' and stack[-1] == '}')):
stack.pop()
if not stack:
return (i, None)
else:
# Mismatched parentheses
return (-1, None)
elif char == ';':
# Found something that look like end of statements. If we are currently
# expecting a '<', the matching '>' must have been an operator, since
# template argument list should not contain statements.
while stack and stack[-1] == '>':
stack.pop()
if not stack:
return (-1, None)
i -= 1
return (-1, stack)
def ReverseCloseExpression(clean_lines, linenum, pos):
"""If input points to ) or } or ] or >, finds the position that opens it.
If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
linenum/pos that correspond to the opening of the expression.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
pos: A position on the line.
Returns:
A tuple (line, linenum, pos) pointer *at* the opening brace, or
(line, 0, -1) if we never find the matching opening brace. Note
we ignore strings and comments when matching; and the line we
return is the 'cleansed' line at linenum.
"""
line = clean_lines.elided[linenum]
if line[pos] not in ')}]>':
return (line, 0, -1)
# Check last line
(start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
if start_pos > -1:
return (line, linenum, start_pos)
# Continue scanning backward
while stack and linenum > 0:
linenum -= 1
line = clean_lines.elided[linenum]
(start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
if start_pos > -1:
return (line, linenum, start_pos)
# Did not find start of expression before beginning of file, give up
return (line, 0, -1)
def CheckForCopyright(filename, lines, error):
"""Logs an error if no Copyright message appears at the top of the file."""
# We'll say it should occur by line 10. Don't forget there's a
# placeholder line at the front.
for line in xrange(1, min(len(lines), 11)):
if re.search(r'Copyright', lines[line], re.I): break
else: # means no copyright line was found
error(filename, 0, 'legal/copyright', 5,
'No copyright message found. '
'You should have a line: "Copyright [year] "')
def GetIndentLevel(line):
"""Return the number of leading spaces in line.
Args:
line: A string to check.
Returns:
An integer count of leading spaces, possibly zero.
"""
indent = Match(r'^( *)\S', line)
if indent:
return len(indent.group(1))
else:
return 0
def PathSplitToList(path):
"""Returns the path split into a list by the separator.
Args:
path: An absolute or relative path (e.g. '/a/b/c/' or '../a')
Returns:
A list of path components (e.g. ['a', 'b', 'c]).
"""
lst = []
while True:
(head, tail) = os.path.split(path)
if head == path: # absolute paths end
lst.append(head)
break
if tail == path: # relative paths end
lst.append(tail)
break
path = head
lst.append(tail)
lst.reverse()
return lst
def GetHeaderGuardCPPVariable(filename):
"""Returns the CPP variable that should be used as a header guard.
Args:
filename: The name of a C++ header file.
Returns:
The CPP variable that should be used as a header guard in the
named file.
"""
# Restores original filename in case that cpplint is invoked from Emacs's
# flymake.
filename = re.sub(r'_flymake\.h$', '.h', filename)
filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
# Replace 'c++' with 'cpp'.
filename = filename.replace('C++', 'cpp').replace('c++', 'cpp')
fileinfo = FileInfo(filename)
file_path_from_root = fileinfo.RepositoryName()
def FixupPathFromRoot():
if _root_debug:
sys.stderr.write("\n_root fixup, _root = '%s', repository name = '%s'\n"
% (_root, fileinfo.RepositoryName()))
# Process the file path with the --root flag if it was set.
if not _root:
if _root_debug:
sys.stderr.write("_root unspecified\n")
return file_path_from_root
def StripListPrefix(lst, prefix):
# f(['x', 'y'], ['w, z']) -> None (not a valid prefix)
if lst[:len(prefix)] != prefix:
return None
# f(['a, 'b', 'c', 'd'], ['a', 'b']) -> ['c', 'd']
return lst[(len(prefix)):]
# root behavior:
# --root=subdir , lstrips subdir from the header guard
maybe_path = StripListPrefix(PathSplitToList(file_path_from_root),
PathSplitToList(_root))
if _root_debug:
sys.stderr.write(("_root lstrip (maybe_path=%s, file_path_from_root=%s," +
" _root=%s)\n") % (maybe_path, file_path_from_root, _root))
if maybe_path:
return os.path.join(*maybe_path)
# --root=.. , will prepend the outer directory to the header guard
full_path = fileinfo.FullName()
# adapt slashes for windows
root_abspath = os.path.abspath(_root).replace('\\', '/')
maybe_path = StripListPrefix(PathSplitToList(full_path),
PathSplitToList(root_abspath))
if _root_debug:
sys.stderr.write(("_root prepend (maybe_path=%s, full_path=%s, " +
"root_abspath=%s)\n") % (maybe_path, full_path, root_abspath))
if maybe_path:
return os.path.join(*maybe_path)
if _root_debug:
sys.stderr.write("_root ignore, returning %s\n" % (file_path_from_root))
# --root=FAKE_DIR is ignored
return file_path_from_root
file_path_from_root = FixupPathFromRoot()
return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
def CheckForHeaderGuard(filename, clean_lines, error):
"""Checks that the file contains a header guard.
Logs an error if no #ifndef header guard is present. For other
headers, checks that the full pathname is used.
Args:
filename: The name of the C++ header file.
clean_lines: A CleansedLines instance containing the file.
error: The function to call with any errors found.
"""
# Don't check for header guards if there are error suppression
# comments somewhere in this file.
#
# Because this is silencing a warning for a nonexistent line, we
# only support the very specific NOLINT(build/header_guard) syntax,
# and not the general NOLINT or NOLINT(*) syntax.
raw_lines = clean_lines.lines_without_raw_strings
for i in raw_lines:
if Search(r'//\s*NOLINT\(build/header_guard\)', i):
return
# Allow pragma once instead of header guards
for i in raw_lines:
if Search(r'^\s*#pragma\s+once', i):
return
cppvar = GetHeaderGuardCPPVariable(filename)
ifndef = ''
ifndef_linenum = 0
define = ''
endif = ''
endif_linenum = 0
for linenum, line in enumerate(raw_lines):
linesplit = line.split()
if len(linesplit) >= 2:
# find the first occurrence of #ifndef and #define, save arg
if not ifndef and linesplit[0] == '#ifndef':
# set ifndef to the header guard presented on the #ifndef line.
ifndef = linesplit[1]
ifndef_linenum = linenum
if not define and linesplit[0] == '#define':
define = linesplit[1]
# find the last occurrence of #endif, save entire line
if line.startswith('#endif'):
endif = line
endif_linenum = linenum
if not ifndef or not define or ifndef != define:
error(filename, 0, 'build/header_guard', 5,
'No #ifndef header guard found, suggested CPP variable is: %s' %
cppvar)
return
# The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
# for backward compatibility.
if ifndef != cppvar:
error_level = 0
if ifndef != cppvar + '_':
error_level = 5
ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
error)
error(filename, ifndef_linenum, 'build/header_guard', error_level,
'#ifndef header guard has wrong style, please use: %s' % cppvar)
# Check for "//" comments on endif line.
ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
error)
match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
if match:
if match.group(1) == '_':
# Issue low severity warning for deprecated double trailing underscore
error(filename, endif_linenum, 'build/header_guard', 0,
'#endif line should be "#endif // %s"' % cppvar)
return
# Didn't find the corresponding "//" comment. If this file does not
# contain any "//" comments at all, it could be that the compiler
# only wants "/**/" comments, look for those instead.
no_single_line_comments = True
for i in xrange(1, len(raw_lines) - 1):
line = raw_lines[i]
if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
no_single_line_comments = False
break
if no_single_line_comments:
match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
if match:
if match.group(1) == '_':
# Low severity warning for double trailing underscore
error(filename, endif_linenum, 'build/header_guard', 0,
'#endif line should be "#endif /* %s */"' % cppvar)
return
# Didn't find anything
error(filename, endif_linenum, 'build/header_guard', 5,
'#endif line should be "#endif // %s"' % cppvar)
def CheckHeaderFileIncluded(filename, include_state, error):
"""Logs an error if a source file does not include its header."""
# Do not check test files
fileinfo = FileInfo(filename)
if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
return
for ext in GetHeaderExtensions():
basefilename = filename[0:len(filename) - len(fileinfo.Extension())]
headerfile = basefilename + '.' + ext
if not os.path.exists(headerfile):
continue
headername = FileInfo(headerfile).RepositoryName()
first_include = None
include_uses_unix_dir_aliases = False
for section_list in include_state.include_list:
for f in section_list:
include_text = f[0]
if "./" in include_text:
include_uses_unix_dir_aliases = True
if headername in include_text or include_text in headername:
return
if not first_include:
first_include = f[1]
message = '%s should include its header file %s' % (fileinfo.RepositoryName(), headername)
if include_uses_unix_dir_aliases:
message += ". Relative paths like . and .. are not allowed."
error(filename, first_include, 'build/include', 5, message)
def CheckForBadCharacters(filename, lines, error):
"""Logs an error for each line containing bad characters.
Two kinds of bad characters:
1. Unicode replacement characters: These indicate that either the file
contained invalid UTF-8 (likely) or Unicode replacement characters (which
it shouldn't). Note that it's possible for this to throw off line
numbering if the invalid UTF-8 occurred adjacent to a newline.
2. NUL bytes. These are problematic for some tools.
Args:
filename: The name of the current file.
lines: An array of strings, each representing a line of the file.
error: The function to call with any errors found.
"""
for linenum, line in enumerate(lines):
if unicode_escape_decode('\ufffd') in line:
error(filename, linenum, 'readability/utf8', 5,
'Line contains invalid UTF-8 (or Unicode replacement character).')
if '\0' in line:
error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
def CheckForNewlineAtEOF(filename, lines, error):
"""Logs an error if there is no newline char at the end of the file.
Args:
filename: The name of the current file.
lines: An array of strings, each representing a line of the file.
error: The function to call with any errors found.
"""
# The array lines() was created by adding two newlines to the
# original file (go figure), then splitting on \n.
# To verify that the file ends in \n, we just have to make sure the
# last-but-two element of lines() exists and is empty.
if len(lines) < 3 or lines[-2]:
error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
'Could not find a newline character at the end of the file.')
def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
"""Logs an error if we see /* ... */ or "..." that extend past one line.
/* ... */ comments are legit inside macros, for one line.
Otherwise, we prefer // comments, so it's ok to warn about the
other. Likewise, it's ok for strings to extend across multiple
lines, as long as a line continuation character (backslash)
terminates each line. Although not currently prohibited by the C++
style guide, it's ugly and unnecessary. We don't do well with either
in this lint program, so we warn about both.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Remove all \\ (escaped backslashes) from the line. They are OK, and the
# second (escaped) slash may trigger later \" detection erroneously.
line = line.replace('\\\\', '')
if line.count('/*') > line.count('*/'):
error(filename, linenum, 'readability/multiline_comment', 5,
'Complex multi-line /*...*/-style comment found. '
'Lint may give bogus warnings. '
'Consider replacing these with //-style comments, '
'with #if 0...#endif, '
'or with more clearly structured multi-line comments.')
if (line.count('"') - line.count('\\"')) % 2:
error(filename, linenum, 'readability/multiline_string', 5,
'Multi-line string ("...") found. This lint script doesn\'t '
'do well with such strings, and may give bogus warnings. '
'Use C++11 raw strings or concatenation instead.')
# (non-threadsafe name, thread-safe alternative, validation pattern)
#
# The validation pattern is used to eliminate false positives such as:
# _rand(); // false positive due to substring match.
# ->rand(); // some member function rand().
# ACMRandom rand(seed); // some variable named rand.
# ISAACRandom rand(); // another variable named rand.
#
# Basically we require the return value of these functions to be used
# in some expression context on the same line by matching on some
# operator before the function name. This eliminates constructors and
# member function calls.
_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
_THREADING_LIST = (
('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
('strtok(', 'strtok_r(',
_UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
)
def CheckPosixThreading(filename, clean_lines, linenum, error):
"""Checks for calls to thread-unsafe functions.
Much code has been originally written without consideration of
multi-threading. Also, engineers are relying on their old experience;
they have learned posix before threading extensions were added. These
tests guide the engineers to use thread-safe functions (when using
posix directly).
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
# Additional pattern matching check to confirm that this is the
# function we are looking for
if Search(pattern, line):
error(filename, linenum, 'runtime/threadsafe_fn', 2,
'Consider using ' + multithread_safe_func +
'...) instead of ' + single_thread_func +
'...) for improved thread safety.')
def CheckVlogArguments(filename, clean_lines, linenum, error):
"""Checks that VLOG() is only used for defining a logging level.
For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
VLOG(FATAL) are not.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
error(filename, linenum, 'runtime/vlog', 5,
'VLOG() should be used with numeric verbosity level. '
'Use LOG() if you want symbolic severity levels.')
# Matches invalid increment: *count++, which moves pointer instead of
# incrementing a value.
_RE_PATTERN_INVALID_INCREMENT = re.compile(
r'^\s*\*\w+(\+\+|--);')
def CheckInvalidIncrement(filename, clean_lines, linenum, error):
"""Checks for invalid increment *count++.
For example following function:
void increment_counter(int* count) {
*count++;
}
is invalid, because it effectively does count++, moving pointer, and should
be replaced with ++*count, (*count)++ or *count += 1.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
if _RE_PATTERN_INVALID_INCREMENT.match(line):
error(filename, linenum, 'runtime/invalid_increment', 5,
'Changing pointer instead of value (or unused value of operator*).')
def IsMacroDefinition(clean_lines, linenum):
if Search(r'^#define', clean_lines[linenum]):
return True
if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
return True
return False
def IsForwardClassDeclaration(clean_lines, linenum):
return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
class _BlockInfo(object):
"""Stores information about a generic block of code."""
def __init__(self, linenum, seen_open_brace):
self.starting_linenum = linenum
self.seen_open_brace = seen_open_brace
self.open_parentheses = 0
self.inline_asm = _NO_ASM
self.check_namespace_indentation = False
def CheckBegin(self, filename, clean_lines, linenum, error):
"""Run checks that applies to text up to the opening brace.
This is mostly for checking the text after the class identifier
and the "{", usually where the base class is specified. For other
blocks, there isn't much to check, so we always pass.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
pass
def CheckEnd(self, filename, clean_lines, linenum, error):
"""Run checks that applies to text after the closing brace.
This is mostly used for checking end of namespace comments.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
pass
def IsBlockInfo(self):
"""Returns true if this block is a _BlockInfo.
This is convenient for verifying that an object is an instance of
a _BlockInfo, but not an instance of any of the derived classes.
Returns:
True for this class, False for derived classes.
"""
return self.__class__ == _BlockInfo
class _ExternCInfo(_BlockInfo):
"""Stores information about an 'extern "C"' block."""
def __init__(self, linenum):
_BlockInfo.__init__(self, linenum, True)
class _ClassInfo(_BlockInfo):
"""Stores information about a class."""
def __init__(self, name, class_or_struct, clean_lines, linenum):
_BlockInfo.__init__(self, linenum, False)
self.name = name
self.is_derived = False
self.check_namespace_indentation = True
if class_or_struct == 'struct':
self.access = 'public'
self.is_struct = True
else:
self.access = 'private'
self.is_struct = False
# Remember initial indentation level for this class. Using raw_lines here
# instead of elided to account for leading comments.
self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
# Try to find the end of the class. This will be confused by things like:
# class A {
# } *x = { ...
#
# But it's still good enough for CheckSectionSpacing.
self.last_line = 0
depth = 0
for i in range(linenum, clean_lines.NumLines()):
line = clean_lines.elided[i]
depth += line.count('{') - line.count('}')
if not depth:
self.last_line = i
break
def CheckBegin(self, filename, clean_lines, linenum, error):
# Look for a bare ':'
if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
self.is_derived = True
def CheckEnd(self, filename, clean_lines, linenum, error):
# If there is a DISALLOW macro, it should appear near the end of
# the class.
seen_last_thing_in_class = False
for i in xrange(linenum - 1, self.starting_linenum, -1):
match = Search(
r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
self.name + r'\)',
clean_lines.elided[i])
if match:
if seen_last_thing_in_class:
error(filename, i, 'readability/constructors', 3,
match.group(1) + ' should be the last thing in the class')
break
if not Match(r'^\s*$', clean_lines.elided[i]):
seen_last_thing_in_class = True
# Check that closing brace is aligned with beginning of the class.
# Only do this if the closing brace is indented by only whitespaces.
# This means we will not check single-line class definitions.
indent = Match(r'^( *)\}', clean_lines.elided[linenum])
if indent and len(indent.group(1)) != self.class_indent:
if self.is_struct:
parent = 'struct ' + self.name
else:
parent = 'class ' + self.name
error(filename, linenum, 'whitespace/indent', 3,
'Closing brace should be aligned with beginning of %s' % parent)
class _NamespaceInfo(_BlockInfo):
"""Stores information about a namespace."""
def __init__(self, name, linenum):
_BlockInfo.__init__(self, linenum, False)
self.name = name or ''
self.check_namespace_indentation = True
def CheckEnd(self, filename, clean_lines, linenum, error):
"""Check end of namespace comments."""
line = clean_lines.raw_lines[linenum]
# Check how many lines is enclosed in this namespace. Don't issue
# warning for missing namespace comments if there aren't enough
# lines. However, do apply checks if there is already an end of
# namespace comment and it's incorrect.
#
# TODO(unknown): We always want to check end of namespace comments
# if a namespace is large, but sometimes we also want to apply the
# check if a short namespace contained nontrivial things (something
# other than forward declarations). There is currently no logic on
# deciding what these nontrivial things are, so this check is
# triggered by namespace size only, which works most of the time.
if (linenum - self.starting_linenum < 10
and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
return
# Look for matching comment at end of namespace.
#
# Note that we accept C style "/* */" comments for terminating
# namespaces, so that code that terminate namespaces inside
# preprocessor macros can be cpplint clean.
#
# We also accept stuff like "// end of namespace ." with the
# period at the end.
#
# Besides these, we don't accept anything else, otherwise we might
# get false negatives when existing comment is a substring of the
# expected namespace.
if self.name:
# Named namespace
if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
re.escape(self.name) + r'[\*/\.\\\s]*$'),
line):
error(filename, linenum, 'readability/namespace', 5,
'Namespace should be terminated with "// namespace %s"' %
self.name)
else:
# Anonymous namespace
if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
# If "// namespace anonymous" or "// anonymous namespace (more text)",
# mention "// anonymous namespace" as an acceptable form
if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
error(filename, linenum, 'readability/namespace', 5,
'Anonymous namespace should be terminated with "// namespace"'
' or "// anonymous namespace"')
else:
error(filename, linenum, 'readability/namespace', 5,
'Anonymous namespace should be terminated with "// namespace"')
class _PreprocessorInfo(object):
"""Stores checkpoints of nesting stacks when #if/#else is seen."""
def __init__(self, stack_before_if):
# The entire nesting stack before #if
self.stack_before_if = stack_before_if
# The entire nesting stack up to #else
self.stack_before_else = []
# Whether we have already seen #else or #elif
self.seen_else = False
class NestingState(object):
"""Holds states related to parsing braces."""
def __init__(self):
# Stack for tracking all braces. An object is pushed whenever we
# see a "{", and popped when we see a "}". Only 3 types of
# objects are possible:
# - _ClassInfo: a class or struct.
# - _NamespaceInfo: a namespace.
# - _BlockInfo: some other type of block.
self.stack = []
# Top of the previous stack before each Update().
#
# Because the nesting_stack is updated at the end of each line, we
# had to do some convoluted checks to find out what is the current
# scope at the beginning of the line. This check is simplified by
# saving the previous top of nesting stack.
#
# We could save the full stack, but we only need the top. Copying
# the full nesting stack would slow down cpplint by ~10%.
self.previous_stack_top = []
# Stack of _PreprocessorInfo objects.
self.pp_stack = []
def SeenOpenBrace(self):
"""Check if we have seen the opening brace for the innermost block.
Returns:
True if we have seen the opening brace, False if the innermost
block is still expecting an opening brace.
"""
return (not self.stack) or self.stack[-1].seen_open_brace
def InNamespaceBody(self):
"""Check if we are currently one level inside a namespace body.
Returns:
True if top of the stack is a namespace block, False otherwise.
"""
return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
def InExternC(self):
"""Check if we are currently one level inside an 'extern "C"' block.
Returns:
True if top of the stack is an extern block, False otherwise.
"""
return self.stack and isinstance(self.stack[-1], _ExternCInfo)
def InClassDeclaration(self):
"""Check if we are currently one level inside a class or struct declaration.
Returns:
True if top of the stack is a class/struct, False otherwise.
"""
return self.stack and isinstance(self.stack[-1], _ClassInfo)
def InAsmBlock(self):
"""Check if we are currently one level inside an inline ASM block.
Returns:
True if the top of the stack is a block containing inline ASM.
"""
return self.stack and self.stack[-1].inline_asm != _NO_ASM
def InTemplateArgumentList(self, clean_lines, linenum, pos):
"""Check if current position is inside template argument list.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
pos: position just after the suspected template argument.
Returns:
True if (linenum, pos) is inside template arguments.
"""
while linenum < clean_lines.NumLines():
# Find the earliest character that might indicate a template argument
line = clean_lines.elided[linenum]
match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
if not match:
linenum += 1
pos = 0
continue
token = match.group(1)
pos += len(match.group(0))
# These things do not look like template argument list:
# class Suspect {
# class Suspect x; }
if token in ('{', '}', ';'): return False
# These things look like template argument list:
# template
# template
# template
# template
if token in ('>', '=', '[', ']', '.'): return True
# Check if token is an unmatched '<'.
# If not, move on to the next character.
if token != '<':
pos += 1
if pos >= len(line):
linenum += 1
pos = 0
continue
# We can't be sure if we just find a single '<', and need to
# find the matching '>'.
(_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
if end_pos < 0:
# Not sure if template argument list or syntax error in file
return False
linenum = end_line
pos = end_pos
return False
def UpdatePreprocessor(self, line):
"""Update preprocessor stack.
We need to handle preprocessors due to classes like this:
#ifdef SWIG
struct ResultDetailsPageElementExtensionPoint {
#else
struct ResultDetailsPageElementExtensionPoint : public Extension {
#endif
We make the following assumptions (good enough for most files):
- Preprocessor condition evaluates to true from #if up to first
#else/#elif/#endif.
- Preprocessor condition evaluates to false from #else/#elif up
to #endif. We still perform lint checks on these lines, but
these do not affect nesting stack.
Args:
line: current line to check.
"""
if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
# Beginning of #if block, save the nesting stack here. The saved
# stack will allow us to restore the parsing state in the #else case.
self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
elif Match(r'^\s*#\s*(else|elif)\b', line):
# Beginning of #else block
if self.pp_stack:
if not self.pp_stack[-1].seen_else:
# This is the first #else or #elif block. Remember the
# whole nesting stack up to this point. This is what we
# keep after the #endif.
self.pp_stack[-1].seen_else = True
self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
# Restore the stack to how it was before the #if
self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
else:
# TODO(unknown): unexpected #else, issue warning?
pass
elif Match(r'^\s*#\s*endif\b', line):
# End of #if or #else blocks.
if self.pp_stack:
# If we saw an #else, we will need to restore the nesting
# stack to its former state before the #else, otherwise we
# will just continue from where we left off.
if self.pp_stack[-1].seen_else:
# Here we can just use a shallow copy since we are the last
# reference to it.
self.stack = self.pp_stack[-1].stack_before_else
# Drop the corresponding #if
self.pp_stack.pop()
else:
# TODO(unknown): unexpected #endif, issue warning?
pass
# TODO(unknown): Update() is too long, but we will refactor later.
def Update(self, filename, clean_lines, linenum, error):
"""Update nesting state with current line.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Remember top of the previous nesting stack.
#
# The stack is always pushed/popped and not modified in place, so
# we can just do a shallow copy instead of copy.deepcopy. Using
# deepcopy would slow down cpplint by ~28%.
if self.stack:
self.previous_stack_top = self.stack[-1]
else:
self.previous_stack_top = None
# Update pp_stack
self.UpdatePreprocessor(line)
# Count parentheses. This is to avoid adding struct arguments to
# the nesting stack.
if self.stack:
inner_block = self.stack[-1]
depth_change = line.count('(') - line.count(')')
inner_block.open_parentheses += depth_change
# Also check if we are starting or ending an inline assembly block.
if inner_block.inline_asm in (_NO_ASM, _END_ASM):
if (depth_change != 0 and
inner_block.open_parentheses == 1 and
_MATCH_ASM.match(line)):
# Enter assembly block
inner_block.inline_asm = _INSIDE_ASM
else:
# Not entering assembly block. If previous line was _END_ASM,
# we will now shift to _NO_ASM state.
inner_block.inline_asm = _NO_ASM
elif (inner_block.inline_asm == _INSIDE_ASM and
inner_block.open_parentheses == 0):
# Exit assembly block
inner_block.inline_asm = _END_ASM
# Consume namespace declaration at the beginning of the line. Do
# this in a loop so that we catch same line declarations like this:
# namespace proto2 { namespace bridge { class MessageSet; } }
while True:
# Match start of namespace. The "\b\s*" below catches namespace
# declarations even if it weren't followed by a whitespace, this
# is so that we don't confuse our namespace checker. The
# missing spaces will be flagged by CheckSpacing.
namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
if not namespace_decl_match:
break
new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
self.stack.append(new_namespace)
line = namespace_decl_match.group(2)
if line.find('{') != -1:
new_namespace.seen_open_brace = True
line = line[line.find('{') + 1:]
# Look for a class declaration in whatever is left of the line
# after parsing namespaces. The regexp accounts for decorated classes
# such as in:
# class LOCKABLE API Object {
# };
class_decl_match = Match(
r'^(\s*(?:template\s*<[\w\s<>,:=]*>\s*)?'
r'(class|struct)\s+(?:[a-zA-Z0-9_]+\s+)*(\w+(?:::\w+)*))'
r'(.*)$', line)
if (class_decl_match and
(not self.stack or self.stack[-1].open_parentheses == 0)):
# We do not want to accept classes that are actually template arguments:
# template ,
# template class Ignore3>
# void Function() {};
#
# To avoid template argument cases, we scan forward and look for
# an unmatched '>'. If we see one, assume we are inside a
# template argument list.
end_declaration = len(class_decl_match.group(1))
if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
self.stack.append(_ClassInfo(
class_decl_match.group(3), class_decl_match.group(2),
clean_lines, linenum))
line = class_decl_match.group(4)
# If we have not yet seen the opening brace for the innermost block,
# run checks here.
if not self.SeenOpenBrace():
self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
# Update access control if we are inside a class/struct
if self.stack and isinstance(self.stack[-1], _ClassInfo):
classinfo = self.stack[-1]
access_match = Match(
r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
r':(?:[^:]|$)',
line)
if access_match:
classinfo.access = access_match.group(2)
# Check that access keywords are indented +1 space. Skip this
# check if the keywords are not preceded by whitespaces.
indent = access_match.group(1)
if (len(indent) != classinfo.class_indent + 1 and
Match(r'^\s*$', indent)):
if classinfo.is_struct:
parent = 'struct ' + classinfo.name
else:
parent = 'class ' + classinfo.name
slots = ''
if access_match.group(3):
slots = access_match.group(3)
error(filename, linenum, 'whitespace/indent', 3,
'%s%s: should be indented +1 space inside %s' % (
access_match.group(2), slots, parent))
# Consume braces or semicolons from what's left of the line
while True:
# Match first brace, semicolon, or closed parenthesis.
matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
if not matched:
break
token = matched.group(1)
if token == '{':
# If namespace or class hasn't seen a opening brace yet, mark
# namespace/class head as complete. Push a new block onto the
# stack otherwise.
if not self.SeenOpenBrace():
self.stack[-1].seen_open_brace = True
elif Match(r'^extern\s*"[^"]*"\s*\{', line):
self.stack.append(_ExternCInfo(linenum))
else:
self.stack.append(_BlockInfo(linenum, True))
if _MATCH_ASM.match(line):
self.stack[-1].inline_asm = _BLOCK_ASM
elif token == ';' or token == ')':
# If we haven't seen an opening brace yet, but we already saw
# a semicolon, this is probably a forward declaration. Pop
# the stack for these.
#
# Similarly, if we haven't seen an opening brace yet, but we
# already saw a closing parenthesis, then these are probably
# function arguments with extra "class" or "struct" keywords.
# Also pop these stack for these.
if not self.SeenOpenBrace():
self.stack.pop()
else: # token == '}'
# Perform end of block checks and pop the stack.
if self.stack:
self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
self.stack.pop()
line = matched.group(2)
def InnermostClass(self):
"""Get class info on the top of the stack.
Returns:
A _ClassInfo object if we are inside a class, or None otherwise.
"""
for i in range(len(self.stack), 0, -1):
classinfo = self.stack[i - 1]
if isinstance(classinfo, _ClassInfo):
return classinfo
return None
def CheckCompletedBlocks(self, filename, error):
"""Checks that all classes and namespaces have been completely parsed.
Call this when all lines in a file have been processed.
Args:
filename: The name of the current file.
error: The function to call with any errors found.
"""
# Note: This test can result in false positives if #ifdef constructs
# get in the way of brace matching. See the testBuildClass test in
# cpplint_unittest.py for an example of this.
for obj in self.stack:
if isinstance(obj, _ClassInfo):
error(filename, obj.starting_linenum, 'build/class', 5,
'Failed to find complete declaration of class %s' %
obj.name)
elif isinstance(obj, _NamespaceInfo):
error(filename, obj.starting_linenum, 'build/namespaces', 5,
'Failed to find complete declaration of namespace %s' %
obj.name)
def CheckForNonStandardConstructs(filename, clean_lines, linenum,
nesting_state, error):
r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
Complain about several constructs which gcc-2 accepts, but which are
not standard C++. Warning about these in lint is one way to ease the
transition to new compilers.
- put storage class first (e.g. "static const" instead of "const static").
- "%lld" instead of %qd" in printf-type functions.
- "%1$d" is non-standard in printf-type functions.
- "\%" is an undefined character escape sequence.
- text after #endif is not allowed.
- invalid inner-style forward declaration.
- >? and operators, and their >?= and = cousins.
Additionally, check for constructor/destructor style violations and reference
members, as it is very convenient to do so while checking for
gcc-2 compliance.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
nesting_state: A NestingState instance which maintains information about
the current stack of nested blocks being parsed.
error: A callable to which errors are reported, which takes 4 arguments:
filename, line number, error level, and message
"""
# Remove comments from the line, but leave in strings for now.
line = clean_lines.lines[linenum]
if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
error(filename, linenum, 'runtime/printf_format', 3,
'%q in format strings is deprecated. Use %ll instead.')
if Search(r'printf\s*\(.*".*%\d+\$', line):
error(filename, linenum, 'runtime/printf_format', 2,
'%N$ formats are unconventional. Try rewriting to avoid them.')
# Remove escaped backslashes before looking for undefined escapes.
line = line.replace('\\\\', '')
if Search(r'("|\').*\\(%|\[|\(|{)', line):
error(filename, linenum, 'build/printf_format', 3,
'%, [, (, and { are undefined character escapes. Unescape them.')
# For the rest, work with both comments and strings removed.
line = clean_lines.elided[linenum]
if Search(r'\b(const|volatile|void|char|short|int|long'
r'|float|double|signed|unsigned'
r'|schar|u?int8|u?int16|u?int32|u?int64)'
r'\s+(register|static|extern|typedef)\b',
line):
error(filename, linenum, 'build/storage_class', 5,
'Storage-class specifier (static, extern, typedef, etc) should be '
'at the beginning of the declaration.')
if Match(r'\s*#\s*endif\s*[^/\s]+', line):
error(filename, linenum, 'build/endif_comment', 5,
'Uncommented text after #endif is non-standard. Use a comment.')
if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
error(filename, linenum, 'build/forward_decl', 5,
'Inner-style forward declarations are invalid. Remove this line.')
if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
line):
error(filename, linenum, 'build/deprecated', 3,
'>? and (max and min) operators are non-standard and deprecated.')
if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
# TODO(unknown): Could it be expanded safely to arbitrary references,
# without triggering too many false positives? The first
# attempt triggered 5 warnings for mostly benign code in the regtest, hence
# the restriction.
# Here's the original regexp, for the reference:
# type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
# r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
error(filename, linenum, 'runtime/member_string_references', 2,
'const string& members are dangerous. It is much better to use '
'alternatives, such as pointers or simple constants.')
# Everything else in this function operates on class declarations.
# Return early if the top of the nesting stack is not a class, or if
# the class head is not completed yet.
classinfo = nesting_state.InnermostClass()
if not classinfo or not classinfo.seen_open_brace:
return
# The class may have been declared with namespace or classname qualifiers.
# The constructor and destructor will not have those qualifiers.
base_classname = classinfo.name.split('::')[-1]
# Look for single-argument constructors that aren't marked explicit.
# Technically a valid construct, but against style.
explicit_constructor_match = Match(
r'\s+(?:(?:inline|constexpr)\s+)*(explicit\s+)?'
r'(?:(?:inline|constexpr)\s+)*%s\s*'
r'\(((?:[^()]|\([^()]*\))*)\)'
% re.escape(base_classname),
line)
if explicit_constructor_match:
is_marked_explicit = explicit_constructor_match.group(1)
if not explicit_constructor_match.group(2):
constructor_args = []
else:
constructor_args = explicit_constructor_match.group(2).split(',')
# collapse arguments so that commas in template parameter lists and function
# argument parameter lists don't split arguments in two
i = 0
while i < len(constructor_args):
constructor_arg = constructor_args[i]
while (constructor_arg.count('<') > constructor_arg.count('>') or
constructor_arg.count('(') > constructor_arg.count(')')):
constructor_arg += ',' + constructor_args[i + 1]
del constructor_args[i + 1]
constructor_args[i] = constructor_arg
i += 1
variadic_args = [arg for arg in constructor_args if '&&...' in arg]
defaulted_args = [arg for arg in constructor_args if '=' in arg]
noarg_constructor = (not constructor_args or # empty arg list
# 'void' arg specifier
(len(constructor_args) == 1 and
constructor_args[0].strip() == 'void'))
onearg_constructor = ((len(constructor_args) == 1 and # exactly one arg
not noarg_constructor) or
# all but at most one arg defaulted
(len(constructor_args) >= 1 and
not noarg_constructor and
len(defaulted_args) >= len(constructor_args) - 1) or
# variadic arguments with zero or one argument
(len(constructor_args) <= 2 and
len(variadic_args) >= 1))
initializer_list_constructor = bool(
onearg_constructor and
Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
copy_constructor = bool(
onearg_constructor and
Match(r'((const\s+(volatile\s+)?)?|(volatile\s+(const\s+)?))?'
r'%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
% re.escape(base_classname), constructor_args[0].strip()))
if (not is_marked_explicit and
onearg_constructor and
not initializer_list_constructor and
not copy_constructor):
if defaulted_args or variadic_args:
error(filename, linenum, 'runtime/explicit', 5,
'Constructors callable with one argument '
'should be marked explicit.')
else:
error(filename, linenum, 'runtime/explicit', 5,
'Single-parameter constructors should be marked explicit.')
elif is_marked_explicit and not onearg_constructor:
if noarg_constructor:
error(filename, linenum, 'runtime/explicit', 5,
'Zero-parameter constructors should not be marked explicit.')
def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
"""Checks for the correctness of various spacing around function calls.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Since function calls often occur inside if/for/while/switch
# expressions - which have their own, more liberal conventions - we
# first see if we should be looking inside such an expression for a
# function call, to which we can apply more strict standards.
fncall = line # if there's no control flow construct, look at whole line
for pattern in (r'\bif\s*\((.*)\)\s*{',
r'\bfor\s*\((.*)\)\s*{',
r'\bwhile\s*\((.*)\)\s*[{;]',
r'\bswitch\s*\((.*)\)\s*{'):
match = Search(pattern, line)
if match:
fncall = match.group(1) # look inside the parens for function calls
break
# Except in if/for/while/switch, there should never be space
# immediately inside parens (eg "f( 3, 4 )"). We make an exception
# for nested parens ( (a+b) + c ). Likewise, there should never be
# a space before a ( when it's a function argument. I assume it's a
# function argument when the char before the whitespace is legal in
# a function name (alnum + _) and we're not starting a macro. Also ignore
# pointers and references to arrays and functions coz they're too tricky:
# we use a very simple way to recognize these:
# " (something)(maybe-something)" or
# " (something)(maybe-something," or
# " (something)[something]"
# Note that we assume the contents of [] to be short enough that
# they'll never need to wrap.
if ( # Ignore control structures.
not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
fncall) and
# Ignore pointers/references to functions.
not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
# Ignore pointers/references to arrays.
not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call
error(filename, linenum, 'whitespace/parens', 4,
'Extra space after ( in function call')
elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
error(filename, linenum, 'whitespace/parens', 2,
'Extra space after (')
if (Search(r'\w\s+\(', fncall) and
not Search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and
not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
not Search(r'\bcase\s+\(', fncall)):
# TODO(unknown): Space after an operator function seem to be a common
# error, silence those for now by restricting them to highest verbosity.
if Search(r'\boperator_*\b', line):
error(filename, linenum, 'whitespace/parens', 0,
'Extra space before ( in function call')
else:
error(filename, linenum, 'whitespace/parens', 4,
'Extra space before ( in function call')
# If the ) is followed only by a newline or a { + newline, assume it's
# part of a control statement (if/while/etc), and don't complain
if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
# If the closing parenthesis is preceded by only whitespaces,
# try to give a more descriptive error message.
if Search(r'^\s+\)', fncall):
error(filename, linenum, 'whitespace/parens', 2,
'Closing ) should be moved to the previous line')
else:
error(filename, linenum, 'whitespace/parens', 2,
'Extra space before )')
def IsBlankLine(line):
"""Returns true if the given line is blank.
We consider a line to be blank if the line is empty or consists of
only white spaces.
Args:
line: A line of a string.
Returns:
True, if the given line is blank.
"""
return not line or line.isspace()
def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
error):
is_namespace_indent_item = (
len(nesting_state.stack) > 1 and
nesting_state.stack[-1].check_namespace_indentation and
isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and
nesting_state.previous_stack_top == nesting_state.stack[-2])
if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
clean_lines.elided, line):
CheckItemIndentationInNamespace(filename, clean_lines.elided,
line, error)
def CheckForFunctionLengths(filename, clean_lines, linenum,
function_state, error):
"""Reports for long function bodies.
For an overview why this is done, see:
https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
Uses a simplistic algorithm assuming other style guidelines
(especially spacing) are followed.
Only checks unindented functions, so class members are unchecked.
Trivial bodies are unchecked, so constructors with huge initializer lists
may be missed.
Blank/comment lines are not counted so as to avoid encouraging the removal
of vertical space and comments just to get through a lint check.
NOLINT *on the last line of a function* disables this check.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
function_state: Current function name and lines in body so far.
error: The function to call with any errors found.
"""
lines = clean_lines.lines
line = lines[linenum]
joined_line = ''
starting_func = False
regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ...
match_result = Match(regexp, line)
if match_result:
# If the name is all caps and underscores, figure it's a macro and
# ignore it, unless it's TEST or TEST_F.
function_name = match_result.group(1).split()[-1]
if function_name == 'TEST' or function_name == 'TEST_F' or (
not Match(r'[A-Z_]+$', function_name)):
starting_func = True
if starting_func:
body_found = False
for start_linenum in xrange(linenum, clean_lines.NumLines()):
start_line = lines[start_linenum]
joined_line += ' ' + start_line.lstrip()
if Search(r'(;|})', start_line): # Declarations and trivial functions
body_found = True
break # ... ignore
if Search(r'{', start_line):
body_found = True
function = Search(r'((\w|:)*)\(', line).group(1)
if Match(r'TEST', function): # Handle TEST... macros
parameter_regexp = Search(r'(\(.*\))', joined_line)
if parameter_regexp: # Ignore bad syntax
function += parameter_regexp.group(1)
else:
function += '()'
function_state.Begin(function)
break
if not body_found:
# No body for the function (or evidence of a non-function) was found.
error(filename, linenum, 'readability/fn_size', 5,
'Lint failed to find start of function body.')
elif Match(r'^\}\s*$', line): # function end
function_state.Check(error, filename, linenum)
function_state.End()
elif not Match(r'^\s*$', line):
function_state.Count() # Count non-blank/non-comment lines.
_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
def CheckComment(line, filename, linenum, next_line_start, error):
"""Checks for common mistakes in comments.
Args:
line: The line in question.
filename: The name of the current file.
linenum: The number of the line to check.
next_line_start: The first non-whitespace column of the next line.
error: The function to call with any errors found.
"""
commentpos = line.find('//')
if commentpos != -1:
# Check if the // may be in quotes. If so, ignore it
if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0:
# Allow one space for new scopes, two spaces otherwise:
if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
((commentpos >= 1 and
line[commentpos-1] not in string.whitespace) or
(commentpos >= 2 and
line[commentpos-2] not in string.whitespace))):
error(filename, linenum, 'whitespace/comments', 2,
'At least two spaces is best between code and comments')
# Checks for common mistakes in TODO comments.
comment = line[commentpos:]
match = _RE_PATTERN_TODO.match(comment)
if match:
# One whitespace is correct; zero whitespace is handled elsewhere.
leading_whitespace = match.group(1)
if len(leading_whitespace) > 1:
error(filename, linenum, 'whitespace/todo', 2,
'Too many spaces before TODO')
username = match.group(2)
if not username:
error(filename, linenum, 'readability/todo', 2,
'Missing username in TODO; it should look like '
'"// TODO(my_username): Stuff."')
middle_whitespace = match.group(3)
# Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
if middle_whitespace != ' ' and middle_whitespace != '':
error(filename, linenum, 'whitespace/todo', 2,
'TODO(my_username) should be followed by a space')
# If the comment contains an alphanumeric character, there
# should be a space somewhere between it and the // unless
# it's a /// or //! Doxygen comment.
if (Match(r'//[^ ]*\w', comment) and
not Match(r'(///|//\!)(\s+|$)', comment)):
error(filename, linenum, 'whitespace/comments', 4,
'Should have a space between // and comment')
def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
"""Checks for the correctness of various spacing issues in the code.
Things we check for: spaces around operators, spaces after
if/for/while/switch, no spaces around parens in function calls, two
spaces between code and comment, don't start a block with a blank
line, don't end a function with a blank line, don't add a blank line
after public/protected/private, don't have too many blank lines in a row.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
nesting_state: A NestingState instance which maintains information about
the current stack of nested blocks being parsed.
error: The function to call with any errors found.
"""
# Don't use "elided" lines here, otherwise we can't check commented lines.
# Don't want to use "raw" either, because we don't want to check inside C++11
# raw strings,
raw = clean_lines.lines_without_raw_strings
line = raw[linenum]
# Before nixing comments, check if the line is blank for no good
# reason. This includes the first line after a block is opened, and
# blank lines at the end of a function (ie, right before a line like '}'
#
# Skip all the blank line checks if we are immediately inside a
# namespace body. In other words, don't issue blank line warnings
# for this block:
# namespace {
#
# }
#
# A warning about missing end of namespace comments will be issued instead.
#
# Also skip blank line checks for 'extern "C"' blocks, which are formatted
# like namespaces.
if (IsBlankLine(line) and
not nesting_state.InNamespaceBody() and
not nesting_state.InExternC()):
elided = clean_lines.elided
prev_line = elided[linenum - 1]
prevbrace = prev_line.rfind('{')
# TODO(unknown): Don't complain if line before blank line, and line after,
# both start with alnums and are indented the same amount.
# This ignores whitespace at the start of a namespace block
# because those are not usually indented.
if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
# OK, we have a blank line at the start of a code block. Before we
# complain, we check if it is an exception to the rule: The previous
# non-empty line has the parameters of a function header that are indented
# 4 spaces (because they did not fit in a 80 column line when placed on
# the same line as the function name). We also check for the case where
# the previous line is indented 6 spaces, which may happen when the
# initializers of a constructor do not fit into a 80 column line.
exception = False
if Match(r' {6}\w', prev_line): # Initializer list?
# We are looking for the opening column of initializer list, which
# should be indented 4 spaces to cause 6 space indentation afterwards.
search_position = linenum-2
while (search_position >= 0
and Match(r' {6}\w', elided[search_position])):
search_position -= 1
exception = (search_position >= 0
and elided[search_position][:5] == ' :')
else:
# Search for the function arguments or an initializer list. We use a
# simple heuristic here: If the line is indented 4 spaces; and we have a
# closing paren, without the opening paren, followed by an opening brace
# or colon (for initializer lists) we assume that it is the last line of
# a function header. If we have a colon indented 4 spaces, it is an
# initializer list.
exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
prev_line)
or Match(r' {4}:', prev_line))
if not exception:
error(filename, linenum, 'whitespace/blank_line', 2,
'Redundant blank line at the start of a code block '
'should be deleted.')
# Ignore blank lines at the end of a block in a long if-else
# chain, like this:
# if (condition1) {
# // Something followed by a blank line
#
# } else if (condition2) {
# // Something else
# }
if linenum + 1 < clean_lines.NumLines():
next_line = raw[linenum + 1]
if (next_line
and Match(r'\s*}', next_line)
and next_line.find('} else ') == -1):
error(filename, linenum, 'whitespace/blank_line', 3,
'Redundant blank line at the end of a code block '
'should be deleted.')
matched = Match(r'\s*(public|protected|private):', prev_line)
if matched:
error(filename, linenum, 'whitespace/blank_line', 3,
'Do not leave a blank line after "%s:"' % matched.group(1))
# Next, check comments
next_line_start = 0
if linenum + 1 < clean_lines.NumLines():
next_line = raw[linenum + 1]
next_line_start = len(next_line) - len(next_line.lstrip())
CheckComment(line, filename, linenum, next_line_start, error)
# get rid of comments and strings
line = clean_lines.elided[linenum]
# You shouldn't have spaces before your brackets, except for C++11 attributes
# or maybe after 'delete []', 'return []() {};', or 'auto [abc, ...] = ...;'.
if (Search(r'\w\s+\[(?!\[)', line) and
not Search(r'(?:auto&?|delete|return)\s+\[', line)):
error(filename, linenum, 'whitespace/braces', 5,
'Extra space before [')
# In range-based for, we wanted spaces before and after the colon, but
# not around "::" tokens that might appear.
if (Search(r'for *\(.*[^:]:[^: ]', line) or
Search(r'for *\(.*[^: ]:[^:]', line)):
error(filename, linenum, 'whitespace/forcolon', 2,
'Missing space around colon in range-based for loop')
def CheckOperatorSpacing(filename, clean_lines, linenum, error):
"""Checks for horizontal spacing around operators.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Don't try to do spacing checks for operator methods. Do this by
# replacing the troublesome characters with something else,
# preserving column position for all other characters.
#
# The replacement is done repeatedly to avoid false positives from
# operators that call operators.
while True:
match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
if match:
line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
else:
break
# We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
# Otherwise not. Note we only check for non-spaces on *both* sides;
# sometimes people put non-spaces on one side when aligning ='s among
# many lines (not that this is behavior that I approve of...)
if ((Search(r'[\w.]=', line) or
Search(r'=[\w.]', line))
and not Search(r'\b(if|while|for) ', line)
# Operators taken from [lex.operators] in C++11 standard.
and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
and not Search(r'operator=', line)):
error(filename, linenum, 'whitespace/operators', 4,
'Missing spaces around =')
# It's ok not to have spaces around binary operators like + - * /, but if
# there's too little whitespace, we get concerned. It's hard to tell,
# though, so we punt on this one for now. TODO.
# You should always have whitespace around binary operators.
#
# Check <= and >= first to avoid false positives with < and >, then
# check non-include lines for spacing around < and >.
#
# If the operator is followed by a comma, assume it's be used in a
# macro context and don't do any checks. This avoids false
# positives.
#
# Note that && is not included here. This is because there are too
# many false positives due to RValue references.
match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
if match:
error(filename, linenum, 'whitespace/operators', 3,
'Missing spaces around %s' % match.group(1))
elif not Match(r'#.*include', line):
# Look for < that is not surrounded by spaces. This is only
# triggered if both sides are missing spaces, even though
# technically should should flag if at least one side is missing a
# space. This is done to avoid some false positives with shifts.
match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
if match:
(_, _, end_pos) = CloseExpression(
clean_lines, linenum, len(match.group(1)))
if end_pos <= -1:
error(filename, linenum, 'whitespace/operators', 3,
'Missing spaces around <')
# Look for > that is not surrounded by spaces. Similar to the
# above, we only trigger if both sides are missing spaces to avoid
# false positives with shifts.
match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
if match:
(_, _, start_pos) = ReverseCloseExpression(
clean_lines, linenum, len(match.group(1)))
if start_pos <= -1:
error(filename, linenum, 'whitespace/operators', 3,
'Missing spaces around >')
# We allow no-spaces around << when used like this: 10<<20, but
# not otherwise (particularly, not when used as streams)
#
# We also allow operators following an opening parenthesis, since
# those tend to be macros that deal with operators.
match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
not (match.group(1) == 'operator' and match.group(2) == ';')):
error(filename, linenum, 'whitespace/operators', 3,
'Missing spaces around <<')
# We allow no-spaces around >> for almost anything. This is because
# C++11 allows ">>" to close nested templates, which accounts for
# most cases when ">>" is not followed by a space.
#
# We still warn on ">>" followed by alpha character, because that is
# likely due to ">>" being used for right shifts, e.g.:
# value >> alpha
#
# When ">>" is used to close templates, the alphanumeric letter that
# follows would be part of an identifier, and there should still be
# a space separating the template type and the identifier.
# type> alpha
match = Search(r'>>[a-zA-Z_]', line)
if match:
error(filename, linenum, 'whitespace/operators', 3,
'Missing spaces around >>')
# There shouldn't be space around unary operators
match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
if match:
error(filename, linenum, 'whitespace/operators', 4,
'Extra space for operator %s' % match.group(1))
def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
"""Checks for horizontal spacing around parentheses.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# No spaces after an if, while, switch, or for
match = Search(r' (if\(|for\(|while\(|switch\()', line)
if match:
error(filename, linenum, 'whitespace/parens', 5,
'Missing space before ( in %s' % match.group(1))
# For if/for/while/switch, the left and right parens should be
# consistent about how many spaces are inside the parens, and
# there should either be zero or one spaces inside the parens.
# We don't want: "if ( foo)" or "if ( foo )".
# Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
match = Search(r'\b(if|for|while|switch)\s*'
r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
line)
if match:
if len(match.group(2)) != len(match.group(4)):
if not (match.group(3) == ';' and
len(match.group(2)) == 1 + len(match.group(4)) or
not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
error(filename, linenum, 'whitespace/parens', 5,
'Mismatching spaces inside () in %s' % match.group(1))
if len(match.group(2)) not in [0, 1]:
error(filename, linenum, 'whitespace/parens', 5,
'Should have zero or one spaces inside ( and ) in %s' %
match.group(1))
def CheckCommaSpacing(filename, clean_lines, linenum, error):
"""Checks for horizontal spacing near commas and semicolons.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
raw = clean_lines.lines_without_raw_strings
line = clean_lines.elided[linenum]
# You should always have a space after a comma (either as fn arg or operator)
#
# This does not apply when the non-space character following the
# comma is another comma, since the only time when that happens is
# for empty macro arguments.
#
# We run this check in two passes: first pass on elided lines to
# verify that lines contain missing whitespaces, second pass on raw
# lines to confirm that those missing whitespaces are not due to
# elided comments.
if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
Search(r',[^,\s]', raw[linenum])):
error(filename, linenum, 'whitespace/comma', 3,
'Missing space after ,')
# You should always have a space after a semicolon
# except for few corner cases
# TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
# space after ;
if Search(r';[^\s};\\)/]', line):
error(filename, linenum, 'whitespace/semicolon', 3,
'Missing space after ;')
def _IsType(clean_lines, nesting_state, expr):
"""Check if expression looks like a type name, returns true if so.
Args:
clean_lines: A CleansedLines instance containing the file.
nesting_state: A NestingState instance which maintains information about
the current stack of nested blocks being parsed.
expr: The expression to check.
Returns:
True, if token looks like a type.
"""
# Keep only the last token in the expression
last_word = Match(r'^.*(\b\S+)$', expr)
if last_word:
token = last_word.group(1)
else:
token = expr
# Match native types and stdint types
if _TYPES.match(token):
return True
# Try a bit harder to match templated types. Walk up the nesting
# stack until we find something that resembles a typename
# declaration for what we are looking for.
typename_pattern = (r'\b(?:typename|class|struct)\s+' + re.escape(token) +
r'\b')
block_index = len(nesting_state.stack) - 1
while block_index >= 0:
if isinstance(nesting_state.stack[block_index], _NamespaceInfo):
return False
# Found where the opening brace is. We want to scan from this
# line up to the beginning of the function, minus a few lines.
# template
# class C
# : public ... { // start scanning here
last_line = nesting_state.stack[block_index].starting_linenum
next_block_start = 0
if block_index > 0:
next_block_start = nesting_state.stack[block_index - 1].starting_linenum
first_line = last_line
while first_line >= next_block_start:
if clean_lines.elided[first_line].find('template') >= 0:
break
first_line -= 1
if first_line < next_block_start:
# Didn't find any "template" keyword before reaching the next block,
# there are probably no template things to check for this block
block_index -= 1
continue
# Look for typename in the specified range
for i in xrange(first_line, last_line + 1, 1):
if Search(typename_pattern, clean_lines.elided[i]):
return True
block_index -= 1
return False
def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error):
"""Checks for horizontal spacing near commas.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
nesting_state: A NestingState instance which maintains information about
the current stack of nested blocks being parsed.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Except after an opening paren, or after another opening brace (in case of
# an initializer list, for instance), you should have spaces before your
# braces when they are delimiting blocks, classes, namespaces etc.
# And since you should never have braces at the beginning of a line,
# this is an easy test. Except that braces used for initialization don't
# follow the same rule; we often don't want spaces before those.
match = Match(r'^(.*[^ ({>]){', line)
if match:
# Try a bit harder to check for brace initialization. This
# happens in one of the following forms:
# Constructor() : initializer_list_{} { ... }
# Constructor{}.MemberFunction()
# Type variable{};
# FunctionCall(type{}, ...);
# LastArgument(..., type{});
# LOG(INFO) << type{} << " ...";
# map_of_type[{...}] = ...;
# ternary = expr ? new type{} : nullptr;
# OuterTemplate{}>
#
# We check for the character following the closing brace, and
# silence the warning if it's one of those listed above, i.e.
# "{.;,)<>]:".
#
# To account for nested initializer list, we allow any number of
# closing braces up to "{;,)<". We can't simply silence the
# warning on first sight of closing brace, because that would
# cause false negatives for things that are not initializer lists.
# Silence this: But not this:
# Outer{ if (...) {
# Inner{...} if (...){ // Missing space before {
# }; }
#
# There is a false negative with this approach if people inserted
# spurious semicolons, e.g. "if (cond){};", but we will catch the
# spurious semicolon with a separate check.
leading_text = match.group(1)
(endline, endlinenum, endpos) = CloseExpression(
clean_lines, linenum, len(match.group(1)))
trailing_text = ''
if endpos > -1:
trailing_text = endline[endpos:]
for offset in xrange(endlinenum + 1,
min(endlinenum + 3, clean_lines.NumLines() - 1)):
trailing_text += clean_lines.elided[offset]
# We also suppress warnings for `uint64_t{expression}` etc., as the style
# guide recommends brace initialization for integral types to avoid
# overflow/truncation.
if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text)
and not _IsType(clean_lines, nesting_state, leading_text)):
error(filename, linenum, 'whitespace/braces', 5,
'Missing space before {')
# Make sure '} else {' has spaces.
if Search(r'}else', line):
error(filename, linenum, 'whitespace/braces', 5,
'Missing space before else')
# You shouldn't have a space before a semicolon at the end of the line.
# There's a special case for "for" since the style guide allows space before
# the semicolon there.
if Search(r':\s*;\s*$', line):
error(filename, linenum, 'whitespace/semicolon', 5,
'Semicolon defining empty statement. Use {} instead.')
elif Search(r'^\s*;\s*$', line):
error(filename, linenum, 'whitespace/semicolon', 5,
'Line contains only semicolon. If this should be an empty statement, '
'use {} instead.')
elif (Search(r'\s+;\s*$', line) and
not Search(r'\bfor\b', line)):
error(filename, linenum, 'whitespace/semicolon', 5,
'Extra space before last semicolon. If this should be an empty '
'statement, use {} instead.')
def IsDecltype(clean_lines, linenum, column):
"""Check if the token ending on (linenum, column) is decltype().
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: the number of the line to check.
column: end column of the token to check.
Returns:
True if this token is decltype() expression, False otherwise.
"""
(text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
if start_col < 0:
return False
if Search(r'\bdecltype\s*$', text[0:start_col]):
return True
return False
def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
"""Checks for additional blank line issues related to sections.
Currently the only thing checked here is blank line before protected/private.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
class_info: A _ClassInfo objects.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
# Skip checks if the class is small, where small means 25 lines or less.
# 25 lines seems like a good cutoff since that's the usual height of
# terminals, and any class that can't fit in one screen can't really
# be considered "small".
#
# Also skip checks if we are on the first line. This accounts for
# classes that look like
# class Foo { public: ... };
#
# If we didn't find the end of the class, last_line would be zero,
# and the check will be skipped by the first condition.
if (class_info.last_line - class_info.starting_linenum <= 24 or
linenum <= class_info.starting_linenum):
return
matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
if matched:
# Issue warning if the line before public/protected/private was
# not a blank line, but don't do this if the previous line contains
# "class" or "struct". This can happen two ways:
# - We are at the beginning of the class.
# - We are forward-declaring an inner class that is semantically
# private, but needed to be public for implementation reasons.
# Also ignores cases where the previous line ends with a backslash as can be
# common when defining classes in C macros.
prev_line = clean_lines.lines[linenum - 1]
if (not IsBlankLine(prev_line) and
not Search(r'\b(class|struct)\b', prev_line) and
not Search(r'\\$', prev_line)):
# Try a bit harder to find the beginning of the class. This is to
# account for multi-line base-specifier lists, e.g.:
# class Derived
# : public Base {
end_class_head = class_info.starting_linenum
for i in range(class_info.starting_linenum, linenum):
if Search(r'\{\s*$', clean_lines.lines[i]):
end_class_head = i
break
if end_class_head < linenum - 1:
error(filename, linenum, 'whitespace/blank_line', 3,
'"%s:" should be preceded by a blank line' % matched.group(1))
def GetPreviousNonBlankLine(clean_lines, linenum):
"""Return the most recent non-blank line and its line number.
Args:
clean_lines: A CleansedLines instance containing the file contents.
linenum: The number of the line to check.
Returns:
A tuple with two elements. The first element is the contents of the last
non-blank line before the current line, or the empty string if this is the
first non-blank line. The second is the line number of that line, or -1
if this is the first non-blank line.
"""
prevlinenum = linenum - 1
while prevlinenum >= 0:
prevline = clean_lines.elided[prevlinenum]
if not IsBlankLine(prevline): # if not a blank line...
return (prevline, prevlinenum)
prevlinenum -= 1
return ('', -1)
def CheckBraces(filename, clean_lines, linenum, error):
"""Looks for misplaced braces (e.g. at the end of line).
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum] # get rid of comments and strings
if Match(r'\s*{\s*$', line):
# We allow an open brace to start a line in the case where someone is using
# braces in a block to explicitly create a new scope, which is commonly used
# to control the lifetime of stack-allocated variables. Braces are also
# used for brace initializers inside function calls. We don't detect this
# perfectly: we just don't complain if the last non-whitespace character on
# the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
# previous line starts a preprocessor block. We also allow a brace on the
# following line if it is part of an array initialization and would not fit
# within the 80 character limit of the preceding line.
prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
if (not Search(r'[,;:}{(]\s*$', prevline) and
not Match(r'\s*#', prevline) and
not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)):
error(filename, linenum, 'whitespace/braces', 4,
'{ should almost always be at the end of the previous line')
# An else clause should be on the same line as the preceding closing brace.
if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
if Match(r'\s*}\s*$', prevline):
error(filename, linenum, 'whitespace/newline', 4,
'An else should appear on the same line as the preceding }')
# If braces come on one side of an else, they should be on both.
# However, we have to worry about "else if" that spans multiple lines!
if Search(r'else if\s*\(', line): # could be multi-line if
brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
# find the ( after the if
pos = line.find('else if')
pos = line.find('(', pos)
if pos > 0:
(endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
brace_on_right = endline[endpos:].find('{') != -1
if brace_on_left != brace_on_right: # must be brace after if
error(filename, linenum, 'readability/braces', 5,
'If an else has a brace on one side, it should have it on both')
elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
error(filename, linenum, 'readability/braces', 5,
'If an else has a brace on one side, it should have it on both')
# Likewise, an else should never have the else clause on the same line
if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
error(filename, linenum, 'whitespace/newline', 4,
'Else clause should never be on same line as else (use 2 lines)')
# In the same way, a do/while should never be on one line
if Match(r'\s*do [^\s{]', line):
error(filename, linenum, 'whitespace/newline', 4,
'do/while clauses should not be on a single line')
# Check single-line if/else bodies. The style guide says 'curly braces are not
# required for single-line statements'. We additionally allow multi-line,
# single statements, but we reject anything with more than one semicolon in
# it. This means that the first semicolon after the if should be at the end of
# its line, and the line after that should have an indent level equal to or
# lower than the if. We also check for ambiguous if/else nesting without
# braces.
if_else_match = Search(r'\b(if\s*(|constexpr)\s*\(|else\b)', line)
if if_else_match and not Match(r'\s*#', line):
if_indent = GetIndentLevel(line)
endline, endlinenum, endpos = line, linenum, if_else_match.end()
if_match = Search(r'\bif\s*(|constexpr)\s*\(', line)
if if_match:
# This could be a multiline if condition, so find the end first.
pos = if_match.end() - 1
(endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
# Check for an opening brace, either directly after the if or on the next
# line. If found, this isn't a single-statement conditional.
if (not Match(r'\s*{', endline[endpos:])
and not (Match(r'\s*$', endline[endpos:])
and endlinenum < (len(clean_lines.elided) - 1)
and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
while (endlinenum < len(clean_lines.elided)
and ';' not in clean_lines.elided[endlinenum][endpos:]):
endlinenum += 1
endpos = 0
if endlinenum < len(clean_lines.elided):
endline = clean_lines.elided[endlinenum]
# We allow a mix of whitespace and closing braces (e.g. for one-liner
# methods) and a single \ after the semicolon (for macros)
endpos = endline.find(';')
if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
# Semicolon isn't the last character, there's something trailing.
# Output a warning if the semicolon is not contained inside
# a lambda expression.
if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
endline):
error(filename, linenum, 'readability/braces', 4,
'If/else bodies with multiple statements require braces')
elif endlinenum < len(clean_lines.elided) - 1:
# Make sure the next line is dedented
next_line = clean_lines.elided[endlinenum + 1]
next_indent = GetIndentLevel(next_line)
# With ambiguous nested if statements, this will error out on the
# if that *doesn't* match the else, regardless of whether it's the
# inner one or outer one.
if (if_match and Match(r'\s*else\b', next_line)
and next_indent != if_indent):
error(filename, linenum, 'readability/braces', 4,
'Else clause should be indented at the same level as if. '
'Ambiguous nested if/else chains require braces.')
elif next_indent > if_indent:
error(filename, linenum, 'readability/braces', 4,
'If/else bodies with multiple statements require braces')
def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
"""Looks for redundant trailing semicolon.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Block bodies should not be followed by a semicolon. Due to C++11
# brace initialization, there are more places where semicolons are
# required than not, so we explicitly list the allowed rules rather
# than listing the disallowed ones. These are the places where "};"
# should be replaced by just "}":
# 1. Some flavor of block following closing parenthesis:
# for (;;) {};
# while (...) {};
# switch (...) {};
# Function(...) {};
# if (...) {};
# if (...) else if (...) {};
#
# 2. else block:
# if (...) else {};
#
# 3. const member function:
# Function(...) const {};
#
# 4. Block following some statement:
# x = 42;
# {};
#
# 5. Block at the beginning of a function:
# Function(...) {
# {};
# }
#
# Note that naively checking for the preceding "{" will also match
# braces inside multi-dimensional arrays, but this is fine since
# that expression will not contain semicolons.
#
# 6. Block following another block:
# while (true) {}
# {};
#
# 7. End of namespaces:
# namespace {};
#
# These semicolons seems far more common than other kinds of
# redundant semicolons, possibly due to people converting classes
# to namespaces. For now we do not warn for this case.
#
# Try matching case 1 first.
match = Match(r'^(.*\)\s*)\{', line)
if match:
# Matched closing parenthesis (case 1). Check the token before the
# matching opening parenthesis, and don't warn if it looks like a
# macro. This avoids these false positives:
# - macro that defines a base class
# - multi-line macro that defines a base class
# - macro that defines the whole class-head
#
# But we still issue warnings for macros that we know are safe to
# warn, specifically:
# - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
# - TYPED_TEST
# - INTERFACE_DEF
# - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
#
# We implement a list of safe macros instead of a list of
# unsafe macros, even though the latter appears less frequently in
# google code and would have been easier to implement. This is because
# the downside for getting the allowed checks wrong means some extra
# semicolons, while the downside for getting disallowed checks wrong
# would result in compile errors.
#
# In addition to macros, we also don't want to warn on
# - Compound literals
# - Lambdas
# - alignas specifier with anonymous structs
# - decltype
closing_brace_pos = match.group(1).rfind(')')
opening_parenthesis = ReverseCloseExpression(
clean_lines, linenum, closing_brace_pos)
if opening_parenthesis[2] > -1:
line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
func = Match(r'^(.*\])\s*$', line_prefix)
if ((macro and
macro.group(1) not in (
'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
(func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
Search(r'\bdecltype$', line_prefix) or
Search(r'\s+=\s*$', line_prefix)):
match = None
if (match and
opening_parenthesis[1] > 1 and
Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
# Multi-line lambda-expression
match = None
else:
# Try matching cases 2-3.
match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
if not match:
# Try matching cases 4-6. These are always matched on separate lines.
#
# Note that we can't simply concatenate the previous line to the
# current line and do a single match, otherwise we may output
# duplicate warnings for the blank line case:
# if (cond) {
# // blank line
# }
prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
if prevline and Search(r'[;{}]\s*$', prevline):
match = Match(r'^(\s*)\{', line)
# Check matching closing brace
if match:
(endline, endlinenum, endpos) = CloseExpression(
clean_lines, linenum, len(match.group(1)))
if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
# Current {} pair is eligible for semicolon check, and we have found
# the redundant semicolon, output warning here.
#
# Note: because we are scanning forward for opening braces, and
# outputting warnings for the matching closing brace, if there are
# nested blocks with trailing semicolons, we will get the error
# messages in reversed order.
# We need to check the line forward for NOLINT
raw_lines = clean_lines.raw_lines
ParseNolintSuppressions(filename, raw_lines[endlinenum-1], endlinenum-1,
error)
ParseNolintSuppressions(filename, raw_lines[endlinenum], endlinenum,
error)
error(filename, endlinenum, 'readability/braces', 4,
"You don't need a ; after a }")
def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
"""Look for empty loop/conditional body with only a single semicolon.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
# Search for loop keywords at the beginning of the line. Because only
# whitespaces are allowed before the keywords, this will also ignore most
# do-while-loops, since those lines should start with closing brace.
#
# We also check "if" blocks here, since an empty conditional block
# is likely an error.
line = clean_lines.elided[linenum]
matched = Match(r'\s*(for|while|if)\s*\(', line)
if matched:
# Find the end of the conditional expression.
(end_line, end_linenum, end_pos) = CloseExpression(
clean_lines, linenum, line.find('('))
# Output warning if what follows the condition expression is a semicolon.
# No warning for all other cases, including whitespace or newline, since we
# have a separate check for semicolons preceded by whitespace.
if end_pos >= 0 and Match(r';', end_line[end_pos:]):
if matched.group(1) == 'if':
error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
'Empty conditional bodies should use {}')
else:
error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
'Empty loop bodies should use {} or continue')
# Check for if statements that have completely empty bodies (no comments)
# and no else clauses.
if end_pos >= 0 and matched.group(1) == 'if':
# Find the position of the opening { for the if statement.
# Return without logging an error if it has no brackets.
opening_linenum = end_linenum
opening_line_fragment = end_line[end_pos:]
# Loop until EOF or find anything that's not whitespace or opening {.
while not Search(r'^\s*\{', opening_line_fragment):
if Search(r'^(?!\s*$)', opening_line_fragment):
# Conditional has no brackets.
return
opening_linenum += 1
if opening_linenum == len(clean_lines.elided):
# Couldn't find conditional's opening { or any code before EOF.
return
opening_line_fragment = clean_lines.elided[opening_linenum]
# Set opening_line (opening_line_fragment may not be entire opening line).
opening_line = clean_lines.elided[opening_linenum]
# Find the position of the closing }.
opening_pos = opening_line_fragment.find('{')
if opening_linenum == end_linenum:
# We need to make opening_pos relative to the start of the entire line.
opening_pos += end_pos
(closing_line, closing_linenum, closing_pos) = CloseExpression(
clean_lines, opening_linenum, opening_pos)
if closing_pos < 0:
return
# Now construct the body of the conditional. This consists of the portion
# of the opening line after the {, all lines until the closing line,
# and the portion of the closing line before the }.
if (clean_lines.raw_lines[opening_linenum] !=
CleanseComments(clean_lines.raw_lines[opening_linenum])):
# Opening line ends with a comment, so conditional isn't empty.
return
if closing_linenum > opening_linenum:
# Opening line after the {. Ignore comments here since we checked above.
bodylist = list(opening_line[opening_pos+1:])
# All lines until closing line, excluding closing line, with comments.
bodylist.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum])
# Closing line before the }. Won't (and can't) have comments.
bodylist.append(clean_lines.elided[closing_linenum][:closing_pos-1])
body = '\n'.join(bodylist)
else:
# If statement has brackets and fits on a single line.
body = opening_line[opening_pos+1:closing_pos-1]
# Check if the body is empty
if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body):
return
# The body is empty. Now make sure there's not an else clause.
current_linenum = closing_linenum
current_line_fragment = closing_line[closing_pos:]
# Loop until EOF or find anything that's not whitespace or else clause.
while Search(r'^\s*$|^(?=\s*else)', current_line_fragment):
if Search(r'^(?=\s*else)', current_line_fragment):
# Found an else clause, so don't log an error.
return
current_linenum += 1
if current_linenum == len(clean_lines.elided):
break
current_line_fragment = clean_lines.elided[current_linenum]
# The body is empty and there's no else clause until EOF or other code.
error(filename, end_linenum, 'whitespace/empty_if_body', 4,
('If statement had no body and no else clause'))
def FindCheckMacro(line):
"""Find a replaceable CHECK-like macro.
Args:
line: line to search on.
Returns:
(macro name, start position), or (None, -1) if no replaceable
macro is found.
"""
for macro in _CHECK_MACROS:
i = line.find(macro)
if i >= 0:
# Find opening parenthesis. Do a regular expression match here
# to make sure that we are matching the expected CHECK macro, as
# opposed to some other macro that happens to contain the CHECK
# substring.
matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
if not matched:
continue
return (macro, len(matched.group(1)))
return (None, -1)
def CheckCheck(filename, clean_lines, linenum, error):
"""Checks the use of CHECK and EXPECT macros.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
# Decide the set of replacement macros that should be suggested
lines = clean_lines.elided
(check_macro, start_pos) = FindCheckMacro(lines[linenum])
if not check_macro:
return
# Find end of the boolean expression by matching parentheses
(last_line, end_line, end_pos) = CloseExpression(
clean_lines, linenum, start_pos)
if end_pos < 0:
return
# If the check macro is followed by something other than a
# semicolon, assume users will log their own custom error messages
# and don't suggest any replacements.
if not Match(r'\s*;', last_line[end_pos:]):
return
if linenum == end_line:
expression = lines[linenum][start_pos + 1:end_pos - 1]
else:
expression = lines[linenum][start_pos + 1:]
for i in xrange(linenum + 1, end_line):
expression += lines[i]
expression += last_line[0:end_pos - 1]
# Parse expression so that we can take parentheses into account.
# This avoids false positives for inputs like "CHECK((a < 4) == b)",
# which is not replaceable by CHECK_LE.
lhs = ''
rhs = ''
operator = None
while expression:
matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
r'==|!=|>=|>|<=|<|\()(.*)$', expression)
if matched:
token = matched.group(1)
if token == '(':
# Parenthesized operand
expression = matched.group(2)
(end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
if end < 0:
return # Unmatched parenthesis
lhs += '(' + expression[0:end]
expression = expression[end:]
elif token in ('&&', '||'):
# Logical and/or operators. This means the expression
# contains more than one term, for example:
# CHECK(42 < a && a < b);
#
# These are not replaceable with CHECK_LE, so bail out early.
return
elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
# Non-relational operator
lhs += token
expression = matched.group(2)
else:
# Relational operator
operator = token
rhs = matched.group(2)
break
else:
# Unparenthesized operand. Instead of appending to lhs one character
# at a time, we do another regular expression match to consume several
# characters at once if possible. Trivial benchmark shows that this
# is more efficient when the operands are longer than a single
# character, which is generally the case.
matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
if not matched:
matched = Match(r'^(\s*\S)(.*)$', expression)
if not matched:
break
lhs += matched.group(1)
expression = matched.group(2)
# Only apply checks if we got all parts of the boolean expression
if not (lhs and operator and rhs):
return
# Check that rhs do not contain logical operators. We already know
# that lhs is fine since the loop above parses out && and ||.
if rhs.find('&&') > -1 or rhs.find('||') > -1:
return
# At least one of the operands must be a constant literal. This is
# to avoid suggesting replacements for unprintable things like
# CHECK(variable != iterator)
#
# The following pattern matches decimal, hex integers, strings, and
# characters (in that order).
lhs = lhs.strip()
rhs = rhs.strip()
match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
if Match(match_constant, lhs) or Match(match_constant, rhs):
# Note: since we know both lhs and rhs, we can provide a more
# descriptive error message like:
# Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
# Instead of:
# Consider using CHECK_EQ instead of CHECK(a == b)
#
# We are still keeping the less descriptive message because if lhs
# or rhs gets long, the error message might become unreadable.
error(filename, linenum, 'readability/check', 2,
'Consider using %s instead of %s(a %s b)' % (
_CHECK_REPLACEMENT[check_macro][operator],
check_macro, operator))
def CheckAltTokens(filename, clean_lines, linenum, error):
"""Check alternative keywords being used in boolean expressions.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Avoid preprocessor lines
if Match(r'^\s*#', line):
return
# Last ditch effort to avoid multi-line comments. This will not help
# if the comment started before the current line or ended after the
# current line, but it catches most of the false positives. At least,
# it provides a way to workaround this warning for people who use
# multi-line comments in preprocessor macros.
#
# TODO(unknown): remove this once cpplint has better support for
# multi-line comments.
if line.find('/*') >= 0 or line.find('*/') >= 0:
return
for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
error(filename, linenum, 'readability/alt_tokens', 2,
'Use operator %s instead of %s' % (
_ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
def GetLineWidth(line):
"""Determines the width of the line in column positions.
Args:
line: A string, which may be a Unicode string.
Returns:
The width of the line in column positions, accounting for Unicode
combining characters and wide characters.
"""
if isinstance(line, unicode):
width = 0
for uc in unicodedata.normalize('NFC', line):
if unicodedata.east_asian_width(uc) in ('W', 'F'):
width += 2
elif not unicodedata.combining(uc):
# Issue 337
# https://mail.python.org/pipermail/python-list/2012-August/628809.html
if (sys.version_info.major, sys.version_info.minor) <= (3, 2):
# https://github.com/python/cpython/blob/2.7/Include/unicodeobject.h#L81
is_wide_build = sysconfig.get_config_var("Py_UNICODE_SIZE") >= 4
# https://github.com/python/cpython/blob/2.7/Objects/unicodeobject.c#L564
is_low_surrogate = 0xDC00 <= ord(uc) <= 0xDFFF
if not is_wide_build and is_low_surrogate:
width -= 1
width += 1
return width
else:
return len(line)
def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
error):
"""Checks rules from the 'C++ style rules' section of cppguide.html.
Most of these rules are hard to test (naming, comment style), but we
do what we can. In particular we check for 2-space indents, line lengths,
tab usage, spaces inside code, etc.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
file_extension: The extension (without the dot) of the filename.
nesting_state: A NestingState instance which maintains information about
the current stack of nested blocks being parsed.
error: The function to call with any errors found.
"""
# Don't use "elided" lines here, otherwise we can't check commented lines.
# Don't want to use "raw" either, because we don't want to check inside C++11
# raw strings,
raw_lines = clean_lines.lines_without_raw_strings
line = raw_lines[linenum]
prev = raw_lines[linenum - 1] if linenum > 0 else ''
if line.find('\t') != -1:
error(filename, linenum, 'whitespace/tab', 1,
'Tab found; better to use spaces')
# One or three blank spaces at the beginning of the line is weird; it's
# hard to reconcile that with 2-space indents.
# NOTE: here are the conditions rob pike used for his tests. Mine aren't
# as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces
# if(RLENGTH > 20) complain = 0;
# if(match($0, " +(error|private|public|protected):")) complain = 0;
# if(match(prev, "&& *$")) complain = 0;
# if(match(prev, "\\|\\| *$")) complain = 0;
# if(match(prev, "[\",=><] *$")) complain = 0;
# if(match($0, " <<")) complain = 0;
# if(match(prev, " +for \\(")) complain = 0;
# if(prevodd && match(prevprev, " +for \\(")) complain = 0;
scope_or_label_pattern = r'\s*(?:public|private|protected|signals)(?:\s+(?:slots\s*)?)?:\s*\\?$'
classinfo = nesting_state.InnermostClass()
initial_spaces = 0
cleansed_line = clean_lines.elided[linenum]
while initial_spaces < len(line) and line[initial_spaces] == ' ':
initial_spaces += 1
# There are certain situations we allow one space, notably for
# section labels, and also lines containing multi-line raw strings.
# We also don't check for lines that look like continuation lines
# (of lines ending in double quotes, commas, equals, or angle brackets)
# because the rules for how to indent those are non-trivial.
if (not Search(r'[",=><] *$', prev) and
(initial_spaces == 1 or initial_spaces == 3) and
not Match(scope_or_label_pattern, cleansed_line) and
not (clean_lines.raw_lines[linenum] != line and
Match(r'^\s*""', line))):
error(filename, linenum, 'whitespace/indent', 3,
'Weird number of spaces at line-start. '
'Are you using a 2-space indent?')
if line and line[-1].isspace():
error(filename, linenum, 'whitespace/end_of_line', 4,
'Line ends in whitespace. Consider deleting these extra spaces.')
# Check if the line is a header guard.
is_header_guard = False
if IsHeaderExtension(file_extension):
cppvar = GetHeaderGuardCPPVariable(filename)
if (line.startswith('#ifndef %s' % cppvar) or
line.startswith('#define %s' % cppvar) or
line.startswith('#endif // %s' % cppvar)):
is_header_guard = True
# #include lines and header guards can be long, since there's no clean way to
# split them.
#
# URLs can be long too. It's possible to split these, but it makes them
# harder to cut&paste.
#
# The "$Id:...$" comment may also get very long without it being the
# developers fault.
#
# Doxygen documentation copying can get pretty long when using an overloaded
# function declaration
if (not line.startswith('#include') and not is_header_guard and
not Match(r'^\s*//.*http(s?)://\S*$', line) and
not Match(r'^\s*//\s*[^\s]*$', line) and
not Match(r'^// \$Id:.*#[0-9]+ \$$', line) and
not Match(r'^\s*/// [@\\](copydoc|copydetails|copybrief) .*$', line)):
line_width = GetLineWidth(line)
if line_width > _line_length:
error(filename, linenum, 'whitespace/line_length', 2,
'Lines should be <= %i characters long' % _line_length)
if (cleansed_line.count(';') > 1 and
# allow simple single line lambdas
not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}\n\r]*\}',
line) and
# for loops are allowed two ;'s (and may run over two lines).
cleansed_line.find('for') == -1 and
(GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
# It's ok to have many commands in a switch case that fits in 1 line
not ((cleansed_line.find('case ') != -1 or
cleansed_line.find('default:') != -1) and
cleansed_line.find('break;') != -1)):
error(filename, linenum, 'whitespace/newline', 0,
'More than one command on the same line')
# Some more style checks
CheckBraces(filename, clean_lines, linenum, error)
CheckTrailingSemicolon(filename, clean_lines, linenum, error)
CheckEmptyBlockBody(filename, clean_lines, linenum, error)
CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
CheckOperatorSpacing(filename, clean_lines, linenum, error)
CheckParenthesisSpacing(filename, clean_lines, linenum, error)
CheckCommaSpacing(filename, clean_lines, linenum, error)
CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
CheckCheck(filename, clean_lines, linenum, error)
CheckAltTokens(filename, clean_lines, linenum, error)
classinfo = nesting_state.InnermostClass()
if classinfo:
CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
# Matches the first component of a filename delimited by -s and _s. That is:
# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
def _DropCommonSuffixes(filename):
"""Drops common suffixes like _test.cc or -inl.h from filename.
For example:
>>> _DropCommonSuffixes('foo/foo-inl.h')
'foo/foo'
>>> _DropCommonSuffixes('foo/bar/foo.cc')
'foo/bar/foo'
>>> _DropCommonSuffixes('foo/foo_internal.h')
'foo/foo'
>>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
'foo/foo_unusualinternal'
Args:
filename: The input filename.
Returns:
The filename with the common suffix removed.
"""
for suffix in itertools.chain(
('%s.%s' % (test_suffix.lstrip('_'), ext)
for test_suffix, ext in itertools.product(_test_suffixes, GetNonHeaderExtensions())),
('%s.%s' % (suffix, ext)
for suffix, ext in itertools.product(['inl', 'imp', 'internal'], GetHeaderExtensions()))):
if (filename.endswith(suffix) and len(filename) > len(suffix) and
filename[-len(suffix) - 1] in ('-', '_')):
return filename[:-len(suffix) - 1]
return os.path.splitext(filename)[0]
def _ClassifyInclude(fileinfo, include, used_angle_brackets, include_order="default"):
"""Figures out what kind of header 'include' is.
Args:
fileinfo: The current file cpplint is running over. A FileInfo instance.
include: The path to a #included file.
used_angle_brackets: True if the #include used <> rather than "".
include_order: "default" or other value allowed in program arguments
Returns:
One of the _XXX_HEADER constants.
For example:
>>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
_C_SYS_HEADER
>>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
_CPP_SYS_HEADER
>>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', True, "standardcfirst")
_OTHER_SYS_HEADER
>>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
_LIKELY_MY_HEADER
>>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
... 'bar/foo_other_ext.h', False)
_POSSIBLE_MY_HEADER
>>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
_OTHER_HEADER
"""
# This is a list of all standard c++ header files, except
# those already checked for above.
is_cpp_header = include in _CPP_HEADERS
# Mark include as C header if in list or in a known folder for standard-ish C headers.
is_std_c_header = (include_order == "default") or (include in _C_HEADERS
# additional linux glibc header folders
or Search(r'(?:%s)\/.*\.h' % "|".join(C_STANDARD_HEADER_FOLDERS), include))
# Headers with C++ extensions shouldn't be considered C system headers
is_system = used_angle_brackets and not os.path.splitext(include)[1] in ['.hpp', '.hxx', '.h++']
if is_system:
if is_cpp_header:
return _CPP_SYS_HEADER
if is_std_c_header:
return _C_SYS_HEADER
else:
return _OTHER_SYS_HEADER
# If the target file and the include we're checking share a
# basename when we drop common extensions, and the include
# lives in . , then it's likely to be owned by the target file.
target_dir, target_base = (
os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
target_dir_pub = os.path.normpath(target_dir + '/../public')
target_dir_pub = target_dir_pub.replace('\\', '/')
if target_base == include_base and (
include_dir == target_dir or
include_dir == target_dir_pub):
return _LIKELY_MY_HEADER
# If the target and include share some initial basename
# component, it's possible the target is implementing the
# include, so it's allowed to be first, but we'll never
# complain if it's not there.
target_first_component = _RE_FIRST_COMPONENT.match(target_base)
include_first_component = _RE_FIRST_COMPONENT.match(include_base)
if (target_first_component and include_first_component and
target_first_component.group(0) ==
include_first_component.group(0)):
return _POSSIBLE_MY_HEADER
return _OTHER_HEADER
def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
"""Check rules that are applicable to #include lines.
Strings on #include lines are NOT removed from elided line, to make
certain tasks easier. However, to prevent false positives, checks
applicable to #include lines in CheckLanguage must be put here.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
include_state: An _IncludeState instance in which the headers are inserted.
error: The function to call with any errors found.
"""
fileinfo = FileInfo(filename)
line = clean_lines.lines[linenum]
# "include" should use the new style "foo/bar.h" instead of just "bar.h"
# Only do this check if the included header follows google naming
# conventions. If not, assume that it's a 3rd party API that
# requires special include conventions.
#
# We also make an exception for Lua headers, which follow google
# naming convention but not the include convention.
match = Match(r'#include\s*"([^/]+\.h)"', line)
if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
error(filename, linenum, 'build/include_subdir', 4,
'Include the directory when naming .h files')
# we shouldn't include a file more than once. actually, there are a
# handful of instances where doing so is okay, but in general it's
# not.
match = _RE_PATTERN_INCLUDE.search(line)
if match:
include = match.group(2)
used_angle_brackets = (match.group(1) == '<')
duplicate_line = include_state.FindHeader(include)
if duplicate_line >= 0:
error(filename, linenum, 'build/include', 4,
'"%s" already included at %s:%s' %
(include, filename, duplicate_line))
return
for extension in GetNonHeaderExtensions():
if (include.endswith('.' + extension) and
os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
error(filename, linenum, 'build/include', 4,
'Do not include .' + extension + ' files from other packages')
return
# We DO want to include a 3rd party looking header if it matches the
# filename. Otherwise we get an erroneous error "...should include its
# header" error later.
third_src_header = False
for ext in GetHeaderExtensions():
basefilename = filename[0:len(filename) - len(fileinfo.Extension())]
headerfile = basefilename + '.' + ext
headername = FileInfo(headerfile).RepositoryName()
if headername in include or include in headername:
third_src_header = True
break
if third_src_header or not _THIRD_PARTY_HEADERS_PATTERN.match(include):
include_state.include_list[-1].append((include, linenum))
# We want to ensure that headers appear in the right order:
# 1) for foo.cc, foo.h (preferred location)
# 2) c system files
# 3) cpp system files
# 4) for foo.cc, foo.h (deprecated location)
# 5) other google headers
#
# We classify each include statement as one of those 5 types
# using a number of techniques. The include_state object keeps
# track of the highest type seen, and complains if we see a
# lower type after that.
error_message = include_state.CheckNextIncludeOrder(
_ClassifyInclude(fileinfo, include, used_angle_brackets, _include_order))
if error_message:
error(filename, linenum, 'build/include_order', 4,
'%s. Should be: %s.h, c system, c++ system, other.' %
(error_message, fileinfo.BaseName()))
canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
if not include_state.IsInAlphabeticalOrder(
clean_lines, linenum, canonical_include):
error(filename, linenum, 'build/include_alpha', 4,
'Include "%s" not in alphabetical order' % include)
include_state.SetLastHeader(canonical_include)
def _GetTextInside(text, start_pattern):
r"""Retrieves all the text between matching open and close parentheses.
Given a string of lines and a regular expression string, retrieve all the text
following the expression and between opening punctuation symbols like
(, [, or {, and the matching close-punctuation symbol. This properly nested
occurrences of the punctuations, so for the text like
printf(a(), b(c()));
a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
start_pattern must match string having an open punctuation symbol at the end.
Args:
text: The lines to extract text. Its comments and strings must be elided.
It can be single line and can span multiple lines.
start_pattern: The regexp string indicating where to start extracting
the text.
Returns:
The extracted text.
None if either the opening string or ending punctuation could not be found.
"""
# TODO(unknown): Audit cpplint.py to see what places could be profitably
# rewritten to use _GetTextInside (and use inferior regexp matching today).
# Give opening punctuations to get the matching close-punctuations.
matching_punctuation = {'(': ')', '{': '}', '[': ']'}
closing_punctuation = set(itervalues(matching_punctuation))
# Find the position to start extracting text.
match = re.search(start_pattern, text, re.M)
if not match: # start_pattern not found in text.
return None
start_position = match.end(0)
assert start_position > 0, (
'start_pattern must ends with an opening punctuation.')
assert text[start_position - 1] in matching_punctuation, (
'start_pattern must ends with an opening punctuation.')
# Stack of closing punctuations we expect to have in text after position.
punctuation_stack = [matching_punctuation[text[start_position - 1]]]
position = start_position
while punctuation_stack and position < len(text):
if text[position] == punctuation_stack[-1]:
punctuation_stack.pop()
elif text[position] in closing_punctuation:
# A closing punctuation without matching opening punctuations.
return None
elif text[position] in matching_punctuation:
punctuation_stack.append(matching_punctuation[text[position]])
position += 1
if punctuation_stack:
# Opening punctuations left without matching close-punctuations.
return None
# punctuations match.
return text[start_position:position - 1]
# Patterns for matching call-by-reference parameters.
#
# Supports nested templates up to 2 levels deep using this messy pattern:
# < (?: < (?: < [^<>]*
# >
# | [^<>] )*
# >
# | [^<>] )*
# >
_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]*
_RE_PATTERN_TYPE = (
r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
r'(?:\w|'
r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
r'::)+')
# A call-by-reference parameter ends with '& identifier'.
_RE_PATTERN_REF_PARAM = re.compile(
r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
# A call-by-const-reference parameter either ends with 'const& identifier'
# or looks like 'const type& identifier' when 'type' is atomic.
_RE_PATTERN_CONST_REF_PARAM = (
r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
# Stream types.
_RE_PATTERN_REF_STREAM_PARAM = (
r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT + r')')
def CheckLanguage(filename, clean_lines, linenum, file_extension,
include_state, nesting_state, error):
"""Checks rules from the 'C++ language rules' section of cppguide.html.
Some of these rules are hard to test (function overloading, using
uint32 inappropriately), but we do the best we can.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
file_extension: The extension (without the dot) of the filename.
include_state: An _IncludeState instance in which the headers are inserted.
nesting_state: A NestingState instance which maintains information about
the current stack of nested blocks being parsed.
error: The function to call with any errors found.
"""
# If the line is empty or consists of entirely a comment, no need to
# check it.
line = clean_lines.elided[linenum]
if not line:
return
match = _RE_PATTERN_INCLUDE.search(line)
if match:
CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
return
# Reset include state across preprocessor directives. This is meant
# to silence warnings for conditional includes.
match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
if match:
include_state.ResetSection(match.group(1))
# Perform other checks now that we are sure that this is not an include line
CheckCasts(filename, clean_lines, linenum, error)
CheckGlobalStatic(filename, clean_lines, linenum, error)
CheckPrintf(filename, clean_lines, linenum, error)
if IsHeaderExtension(file_extension):
# TODO(unknown): check that 1-arg constructors are explicit.
# How to tell it's a constructor?
# (handled in CheckForNonStandardConstructs for now)
# TODO(unknown): check that classes declare or disable copy/assign
# (level 1 error)
pass
# Check if people are using the verboten C basic types. The only exception
# we regularly allow is "unsigned short port" for port.
if Search(r'\bshort port\b', line):
if not Search(r'\bunsigned short port\b', line):
error(filename, linenum, 'runtime/int', 4,
'Use "unsigned short" for ports, not "short"')
else:
match = Search(r'\b(short|long(?! +double)|long long)\b', line)
if match:
error(filename, linenum, 'runtime/int', 4,
'Use int16/int64/etc, rather than the C type %s' % match.group(1))
# Check if some verboten operator overloading is going on
# TODO(unknown): catch out-of-line unary operator&:
# class X {};
# int operator&(const X& x) { return 42; } // unary operator&
# The trick is it's hard to tell apart from binary operator&:
# class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
if Search(r'\boperator\s*&\s*\(\s*\)', line):
error(filename, linenum, 'runtime/operator', 4,
'Unary operator& is dangerous. Do not use it.')
# Check for suspicious usage of "if" like
# } if (a == b) {
if Search(r'\}\s*if\s*\(', line):
error(filename, linenum, 'readability/braces', 4,
'Did you mean "else if"? If not, start a new line for "if".')
# Check for potential format string bugs like printf(foo).
# We constrain the pattern not to pick things like DocidForPrintf(foo).
# Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
# TODO(unknown): Catch the following case. Need to change the calling
# convention of the whole function to process multiple line to handle it.
# printf(
# boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
if printf_args:
match = Match(r'([\w.\->()]+)$', printf_args)
if match and match.group(1) != '__VA_ARGS__':
function_name = re.search(r'\b((?:string)?printf)\s*\(',
line, re.I).group(1)
error(filename, linenum, 'runtime/printf', 4,
'Potential format string bug. Do %s("%%s", %s) instead.'
% (function_name, match.group(1)))
# Check for potential memset bugs like memset(buf, sizeof(buf), 0).
match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
error(filename, linenum, 'runtime/memset', 4,
'Did you mean "memset(%s, 0, %s)"?'
% (match.group(1), match.group(2)))
if Search(r'\busing namespace\b', line):
if Search(r'\bliterals\b', line):
error(filename, linenum, 'build/namespaces_literals', 5,
'Do not use namespace using-directives. '
'Use using-declarations instead.')
else:
error(filename, linenum, 'build/namespaces', 5,
'Do not use namespace using-directives. '
'Use using-declarations instead.')
# Detect variable-length arrays.
match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
match.group(3).find(']') == -1):
# Split the size using space and arithmetic operators as delimiters.
# If any of the resulting tokens are not compile time constants then
# report the error.
tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
is_const = True
skip_next = False
for tok in tokens:
if skip_next:
skip_next = False
continue
if Search(r'sizeof\(.+\)', tok): continue
if Search(r'arraysize\(\w+\)', tok): continue
tok = tok.lstrip('(')
tok = tok.rstrip(')')
if not tok: continue
if Match(r'\d+', tok): continue
if Match(r'0[xX][0-9a-fA-F]+', tok): continue
if Match(r'k[A-Z0-9]\w*', tok): continue
if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
# A catch all for tricky sizeof cases, including 'sizeof expression',
# 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
# requires skipping the next token because we split on ' ' and '*'.
if tok.startswith('sizeof'):
skip_next = True
continue
is_const = False
break
if not is_const:
error(filename, linenum, 'runtime/arrays', 1,
'Do not use variable-length arrays. Use an appropriately named '
"('k' followed by CamelCase) compile-time constant for the size.")
# Check for use of unnamed namespaces in header files. Registration
# macros are typically OK, so we allow use of "namespace {" on lines
# that end with backslashes.
if (IsHeaderExtension(file_extension)
and Search(r'\bnamespace\s*{', line)
and line[-1] != '\\'):
error(filename, linenum, 'build/namespaces_headers', 4,
'Do not use unnamed namespaces in header files. See '
'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
' for more information.')
def CheckGlobalStatic(filename, clean_lines, linenum, error):
"""Check for unsafe global or static objects.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Match two lines at a time to support multiline declarations
if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
line += clean_lines.elided[linenum + 1].strip()
# Check for people declaring static/global STL strings at the top level.
# This is dangerous because the C++ language does not guarantee that
# globals with constructors are initialized before the first access, and
# also because globals can be destroyed when some threads are still running.
# TODO(unknown): Generalize this to also find static unique_ptr instances.
# TODO(unknown): File bugs for clang-tidy to find these.
match = Match(
r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +'
r'([a-zA-Z0-9_:]+)\b(.*)',
line)
# Remove false positives:
# - String pointers (as opposed to values).
# string *pointer
# const string *pointer
# string const *pointer
# string *const pointer
#
# - Functions and template specializations.
# string Function(...
# string Class::Method(...
#
# - Operators. These are matched separately because operator names
# cross non-word boundaries, and trying to match both operators
# and functions at the same time would decrease accuracy of
# matching identifiers.
# string Class::operator*()
if (match and
not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and
not Search(r'\boperator\W', line) and
not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
if Search(r'\bconst\b', line):
error(filename, linenum, 'runtime/string', 4,
'For a static/global string constant, use a C style string '
'instead: "%schar%s %s[]".' %
(match.group(1), match.group(2) or '', match.group(3)))
else:
error(filename, linenum, 'runtime/string', 4,
'Static/global string variables are not permitted.')
if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or
Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
error(filename, linenum, 'runtime/init', 4,
'You seem to be initializing a member variable with itself.')
def CheckPrintf(filename, clean_lines, linenum, error):
"""Check for printf related issues.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# When snprintf is used, the second argument shouldn't be a literal.
match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
if match and match.group(2) != '0':
# If 2nd arg is zero, snprintf is used to calculate size.
error(filename, linenum, 'runtime/printf', 3,
'If you can, use sizeof(%s) instead of %s as the 2nd arg '
'to snprintf.' % (match.group(1), match.group(2)))
# Check if some verboten C functions are being used.
if Search(r'\bsprintf\s*\(', line):
error(filename, linenum, 'runtime/printf', 5,
'Never use sprintf. Use snprintf instead.')
match = Search(r'\b(strcpy|strcat)\s*\(', line)
if match:
error(filename, linenum, 'runtime/printf', 4,
'Almost always, snprintf is better than %s' % match.group(1))
def IsDerivedFunction(clean_lines, linenum):
"""Check if current line contains an inherited function.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
Returns:
True if current line contains a function with "override"
virt-specifier.
"""
# Scan back a few lines for start of current function
for i in xrange(linenum, max(-1, linenum - 10), -1):
match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
if match:
# Look for "override" after the matching closing parenthesis
line, _, closing_paren = CloseExpression(
clean_lines, i, len(match.group(1)))
return (closing_paren >= 0 and
Search(r'\boverride\b', line[closing_paren:]))
return False
def IsOutOfLineMethodDefinition(clean_lines, linenum):
"""Check if current line contains an out-of-line method definition.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
Returns:
True if current line contains an out-of-line method definition.
"""
# Scan back a few lines for start of current function
for i in xrange(linenum, max(-1, linenum - 10), -1):
if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
return False
def IsInitializerList(clean_lines, linenum):
"""Check if current line is inside constructor initializer list.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
Returns:
True if current line appears to be inside constructor initializer
list, False otherwise.
"""
for i in xrange(linenum, 1, -1):
line = clean_lines.elided[i]
if i == linenum:
remove_function_body = Match(r'^(.*)\{\s*$', line)
if remove_function_body:
line = remove_function_body.group(1)
if Search(r'\s:\s*\w+[({]', line):
# A lone colon tend to indicate the start of a constructor
# initializer list. It could also be a ternary operator, which
# also tend to appear in constructor initializer lists as
# opposed to parameter lists.
return True
if Search(r'\}\s*,\s*$', line):
# A closing brace followed by a comma is probably the end of a
# brace-initialized member in constructor initializer list.
return True
if Search(r'[{};]\s*$', line):
# Found one of the following:
# - A closing brace or semicolon, probably the end of the previous
# function.
# - An opening brace, probably the start of current class or namespace.
#
# Current line is probably not inside an initializer list since
# we saw one of those things without seeing the starting colon.
return False
# Got to the beginning of the file without seeing the start of
# constructor initializer list.
return False
def CheckForNonConstReference(filename, clean_lines, linenum,
nesting_state, error):
"""Check for non-const references.
Separate from CheckLanguage since it scans backwards from current
line, instead of scanning forward.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
nesting_state: A NestingState instance which maintains information about
the current stack of nested blocks being parsed.
error: The function to call with any errors found.
"""
# Do nothing if there is no '&' on current line.
line = clean_lines.elided[linenum]
if '&' not in line:
return
# If a function is inherited, current function doesn't have much of
# a choice, so any non-const references should not be blamed on
# derived function.
if IsDerivedFunction(clean_lines, linenum):
return
# Don't warn on out-of-line method definitions, as we would warn on the
# in-line declaration, if it isn't marked with 'override'.
if IsOutOfLineMethodDefinition(clean_lines, linenum):
return
# Long type names may be broken across multiple lines, usually in one
# of these forms:
# LongType
# ::LongTypeContinued &identifier
# LongType::
# LongTypeContinued &identifier
# LongType<
# ...>::LongTypeContinued &identifier
#
# If we detected a type split across two lines, join the previous
# line to current line so that we can match const references
# accordingly.
#
# Note that this only scans back one line, since scanning back
# arbitrary number of lines would be expensive. If you have a type
# that spans more than 2 lines, please use a typedef.
if linenum > 1:
previous = None
if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
# previous_line\n + ::current_line
previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
clean_lines.elided[linenum - 1])
elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
# previous_line::\n + current_line
previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
clean_lines.elided[linenum - 1])
if previous:
line = previous.group(1) + line.lstrip()
else:
# Check for templated parameter that is split across multiple lines
endpos = line.rfind('>')
if endpos > -1:
(_, startline, startpos) = ReverseCloseExpression(
clean_lines, linenum, endpos)
if startpos > -1 and startline < linenum:
# Found the matching < on an earlier line, collect all
# pieces up to current line.
line = ''
for i in xrange(startline, linenum + 1):
line += clean_lines.elided[i].strip()
# Check for non-const references in function parameters. A single '&' may
# found in the following places:
# inside expression: binary & for bitwise AND
# inside expression: unary & for taking the address of something
# inside declarators: reference parameter
# We will exclude the first two cases by checking that we are not inside a
# function body, including one that was just introduced by a trailing '{'.
# TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
if (nesting_state.previous_stack_top and
not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
# Not at toplevel, not within a class, and not within a namespace
return
# Avoid initializer lists. We only need to scan back from the
# current line for something that starts with ':'.
#
# We don't need to check the current line, since the '&' would
# appear inside the second set of parentheses on the current line as
# opposed to the first set.
if linenum > 0:
for i in xrange(linenum - 1, max(0, linenum - 10), -1):
previous_line = clean_lines.elided[i]
if not Search(r'[),]\s*$', previous_line):
break
if Match(r'^\s*:\s+\S', previous_line):
return
# Avoid preprocessors
if Search(r'\\\s*$', line):
return
# Avoid constructor initializer lists
if IsInitializerList(clean_lines, linenum):
return
# We allow non-const references in a few standard places, like functions
# called "swap()" or iostream operators like "<<" or ">>". Do not check
# those function parameters.
#
# We also accept & in static_assert, which looks like a function but
# it's actually a declaration expression.
allowed_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
r'operator\s*[<>][<>]|'
r'static_assert|COMPILE_ASSERT'
r')\s*\(')
if Search(allowed_functions, line):
return
elif not Search(r'\S+\([^)]*$', line):
# Don't see an allowed function on this line. Actually we
# didn't see any function name on this line, so this is likely a
# multi-line parameter list. Try a bit harder to catch this case.
for i in xrange(2):
if (linenum > i and
Search(allowed_functions, clean_lines.elided[linenum - i - 1])):
return
decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body
for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
error(filename, linenum, 'runtime/references', 2,
'Is this a non-const reference? '
'If so, make const or use a pointer: ' +
ReplaceAll(' *<', '<', parameter))
def CheckCasts(filename, clean_lines, linenum, error):
"""Various cast related checks.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
error: The function to call with any errors found.
"""
line = clean_lines.elided[linenum]
# Check to see if they're using an conversion function cast.
# I just try to capture the most common basic types, though there are more.
# Parameterless conversion functions, such as bool(), are allowed as they are
# probably a member operator declaration or default constructor.
match = Search(
r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b'
r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
r'(\([^)].*)', line)
expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
if match and not expecting_function:
matched_type = match.group(2)
# matched_new_or_template is used to silence two false positives:
# - New operators
# - Template arguments with function types
#
# For template arguments, we match on types immediately following
# an opening bracket without any spaces. This is a fast way to
# silence the common case where the function type is the first
# template argument. False negative with less-than comparison is
# avoided because those operators are usually followed by a space.
#
# function // bracket + no space = false positive
# value < double(42) // bracket + space = true positive
matched_new_or_template = match.group(1)
# Avoid arrays by looking for brackets that come after the closing
# parenthesis.
if Match(r'\([^()]+\)\s*\[', match.group(3)):
return
# Other things to ignore:
# - Function pointers
# - Casts to pointer types
# - Placement new
# - Alias declarations
matched_funcptr = match.group(3)
if (matched_new_or_template is None and
not (matched_funcptr and
(Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
matched_funcptr) or
matched_funcptr.startswith('(*)'))) and
not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
not Search(r'new\(\S+\)\s*' + matched_type, line)):
error(filename, linenum, 'readability/casting', 4,
'Using deprecated casting style. '
'Use static_cast<%s>(...) instead' %
matched_type)
if not expecting_function:
CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
# This doesn't catch all cases. Consider (const char * const)"hello".
#
# (char *) "foo" should always be a const_cast (reinterpret_cast won't
# compile).
if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast',
r'\((char\s?\*+\s?)\)\s*"', error):
pass
else:
# Check pointer casts for other than string constants
CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast',
r'\((\w+\s?\*+\s?)\)', error)
# In addition, we look for people taking the address of a cast. This
# is dangerous -- casts can assign to temporaries, so the pointer doesn't
# point where you think.
#
# Some non-identifier character is required before the '&' for the
# expression to be recognized as a cast. These are casts:
# expression = &static_cast(temporary());
# function(&(int*)(temporary()));
#
# This is not a cast:
# reference_type&(int* function_param);
match = Search(
r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
if match:
# Try a better error message when the & is bound to something
# dereferenced by the casted pointer, as opposed to the casted
# pointer itself.
parenthesis_error = False
match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
if match:
_, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
_, y2, x2 = CloseExpression(clean_lines, y1, x1)
if x2 >= 0:
extended_line = clean_lines.elided[y2][x2:]
if y2 < clean_lines.NumLines() - 1:
extended_line += clean_lines.elided[y2 + 1]
if Match(r'\s*(?:->|\[)', extended_line):
parenthesis_error = True
if parenthesis_error:
error(filename, linenum, 'readability/casting', 4,
('Are you taking an address of something dereferenced '
'from a cast? Wrapping the dereferenced expression in '
'parentheses will make the binding more obvious'))
else:
error(filename, linenum, 'runtime/casting', 4,
('Are you taking an address of a cast? '
'This is dangerous: could be a temp var. '
'Take the address before doing the cast, rather than after'))
def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
"""Checks for a C-style cast by looking for the pattern.
Args:
filename: The name of the current file.
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
cast_type: The string for the C++ cast to recommend. This is either
reinterpret_cast, static_cast, or const_cast, depending.
pattern: The regular expression used to find C-style casts.
error: The function to call with any errors found.
Returns:
True if an error was emitted.
False otherwise.
"""
line = clean_lines.elided[linenum]
match = Search(pattern, line)
if not match:
return False
# Exclude lines with keywords that tend to look like casts
context = line[0:match.start(1) - 1]
if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
return False
# Try expanding current context to see if we one level of
# parentheses inside a macro.
if linenum > 0:
for i in xrange(linenum - 1, max(0, linenum - 5), -1):
context = clean_lines.elided[i] + context
if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
return False
# operator++(int) and operator--(int)
if context.endswith(' operator++') or context.endswith(' operator--'):
return False
# A single unnamed argument for a function tends to look like old style cast.
# If we see those, don't issue warnings for deprecated casts.
remainder = line[match.end(0):]
if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
remainder):
return False
# At this point, all that should be left is actual casts.
error(filename, linenum, 'readability/casting', 4,
'Using C-style cast. Use %s<%s>(...) instead' %
(cast_type, match.group(1)))
return True
def ExpectingFunctionArgs(clean_lines, linenum):
"""Checks whether where function type arguments are expected.
Args:
clean_lines: A CleansedLines instance containing the file.
linenum: The number of the line to check.
Returns:
True if the line at 'linenum' is inside something that expects arguments
of function types.
"""
line = clean_lines.elided[linenum]
return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
(linenum >= 2 and
(Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
clean_lines.elided[linenum - 1]) or
Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
clean_lines.elided[linenum - 2]) or
Search(r'\bstd::m?function\s*\<\s*$',
clean_lines.elided[linenum - 1]))))
_HEADERS_CONTAINING_TEMPLATES = (
('', ('deque',)),
('', ('unary_function', 'binary_function',
'plus', 'minus', 'multiplies', 'divides', 'modulus',
'negate',
'equal_to', 'not_equal_to', 'greater', 'less',
'greater_equal', 'less_equal',
'logical_and', 'logical_or', 'logical_not',
'unary_negate', 'not1', 'binary_negate', 'not2',
'bind1st', 'bind2nd',
'pointer_to_unary_function',
'pointer_to_binary_function',
'ptr_fun',
'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
'mem_fun_ref_t',
'const_mem_fun_t', 'const_mem_fun1_t',
'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
'mem_fun_ref',
)),
('', ('numeric_limits',)),
('', ('list',)),
('
ign-cmake-ignition-cmake2_2.10.0/doc/doxygen/api.in 0000664 0001750 0001750 00000320017 14160533245 021742 0 ustar jrivero jrivero # Doxyfile 1.8.14
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all text
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
# built into libc) for the transcoding. See
# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "Ignition @IGN_DESIGNATION_CAP@"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = @PROJECT_VERSION_FULL@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = doxygen
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# The default value is: NO.
CREATE_SUBDIRS = NO
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = YES
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
# page for each member. If set to NO, the documentation of a member will be part
# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 4
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
# Fortran. In the later case the parser tries to guess whether the code is fixed
# or free formatted code, this is the default for Fortran type files), VHDL. For
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
# to that level are automatically included in the table of contents, even if
# they do not have an id attribute.
# Note: This feature currently applies only to Markdown headings.
# Minimum value: 0, maximum value: 99, default value: 0.
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
# TOC_INCLUDE_HEADINGS = 0
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or
# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = YES
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.
GROUP_NESTED_COMPOUNDS = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = YES
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
# The default value is: system dependent.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = YES
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = YES
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = YES
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = YES
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = NO
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if ... \endif and \cond
# ... \endcond blocks.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE = "@IGNITION_CMAKE_DOXYGEN_DIR@/layout.xml"
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = NO
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = YES
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
WARN_AS_ERROR = NO
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
WARN_LOGFILE = ignition-doxygen.warn
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = @IGNITION_DOXYGEN_INPUT@
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
# possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
FILE_PATTERNS = *.hh \
*.h \
*.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = *_TEST.* \
*_TEST[123456789]*.* \
win_dirent.h \
*Private.hh \
*/detail/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS = detail
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS = *.cc \
*.hh \
CMakeLists.txt
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH = @IGNITION_DOXYGEN_IMAGE_PATH@
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
#
#
# where is the value of the INPUT_FILTER tag, and is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
FILTER_PATTERNS = *.hh="sed -e 's/inline\snamespace\s.*\s{$\|ignition::@IGN_DESIGNATION@::\|IGN_DEPRECATED([0-9\.]\+)\|IGNITION_@IGN_DESIGNATION_UPPER@_VISIBLE//g'"
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE = @IGNITION_DOXYGEN_API_MAINPAGE_MD@
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# function all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 3
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = @IGNITION_DOXYGEN_GENHTML@
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER = @IGNITION_CMAKE_DOXYGEN_DIR@/header.html
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER = @IGNITION_CMAKE_DOXYGEN_DIR@/footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 13
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 76
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that
# are dynamically created via Javascript. If disabled, the navigation index will
# consists of multiple levels of tabs that are statically embedded in every HTML
# page. Disable this option to support browsers that do not have Javascript,
# like the Qt help browser.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
# HTML_DYNAMIC_MENUS = YES
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = YES
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: https://developer.apple.com/tools/xcode/), introduced with
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Ignition @IGN_DESIGNATION_CAP@ API Documentation"
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = YES
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# https://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = YES
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment.
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use + S
# (what the is depends on the OS and browser, but it is typically
# , /