358 lines
11 KiB
CMake
358 lines
11 KiB
CMake
# Copyright 2016 The Cartographer Authors
|
|
#
|
|
# 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.
|
|
|
|
include(CMakeParseArguments)
|
|
|
|
macro(_parse_arguments ARGS)
|
|
set(OPTIONS
|
|
USES_BOOST
|
|
USES_CERES
|
|
USES_EIGEN
|
|
USES_GFLAGS
|
|
USES_GLOG
|
|
USES_LUA
|
|
USES_WEBP
|
|
USES_CAIRO
|
|
)
|
|
|
|
# Options only used by projects using Cartographers cmake files.
|
|
list(APPEND OPTIONS
|
|
USES_CARTOGRAPHER
|
|
USES_PCL
|
|
USES_ROS
|
|
USES_YAMLCPP
|
|
)
|
|
set(ONE_VALUE_ARG )
|
|
set(MULTI_VALUE_ARGS SRCS HDRS DEPENDS)
|
|
cmake_parse_arguments(ARG
|
|
"${OPTIONS}" "${ONE_VALUE_ARG}" "${MULTI_VALUE_ARGS}" ${ARGS})
|
|
endmacro(_parse_arguments)
|
|
|
|
macro(_common_compile_stuff VISIBILITY)
|
|
set(TARGET_COMPILE_FLAGS "${TARGET_COMPILE_FLAGS} ${GOOG_CXX_FLAGS}")
|
|
|
|
if(ARG_USES_EIGEN)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${EIGEN3_INCLUDE_DIR}")
|
|
target_link_libraries("${NAME}" ${EIGEN3_LIBRARIES})
|
|
endif()
|
|
|
|
if(ARG_USES_CERES)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${CERES_INCLUDE_DIRS}")
|
|
target_link_libraries("${NAME}" ${CERES_LIBRARIES})
|
|
endif()
|
|
|
|
if(ARG_USES_LUA)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${LUA_INCLUDE_DIR}")
|
|
target_link_libraries("${NAME}" ${LUA_LIBRARIES})
|
|
endif()
|
|
|
|
if(ARG_USES_BOOST)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"{Boost_INCLUDE_DIRS}")
|
|
target_link_libraries("${NAME}" ${Boost_LIBRARIES})
|
|
endif()
|
|
|
|
if(ARG_USES_WEBP)
|
|
target_link_libraries("${NAME}" webp)
|
|
endif()
|
|
|
|
# We rely on Ceres to find glog and gflags for us.
|
|
if(ARG_USES_GLOG)
|
|
target_link_libraries("${NAME}" glog)
|
|
endif()
|
|
|
|
if(ARG_USES_GFLAGS)
|
|
target_link_libraries("${NAME}" gflags)
|
|
endif()
|
|
|
|
if(ARG_USES_ROS)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${catkin_INCLUDE_DIRS}")
|
|
target_link_libraries("${NAME}" ${catkin_LIBRARIES})
|
|
add_dependencies("${NAME}" ${catkin_EXPORTED_TARGETS}
|
|
)
|
|
endif()
|
|
|
|
if(ARG_USES_CARTOGRAPHER)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${CARTOGRAPHER_INCLUDE_DIRS}")
|
|
target_link_libraries("${NAME}" ${CARTOGRAPHER_LIBRARIES})
|
|
endif()
|
|
|
|
if(ARG_USES_PCL)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${PCL_INCLUDE_DIRS}")
|
|
target_link_libraries("${NAME}" ${PCL_LIBRARIES})
|
|
foreach(DEFINITION ${PCL_DEFINITIONS})
|
|
set(TARGET_COMPILE_FLAGS "${TARGET_COMPILE_FLAGS} ${DEFINITION}")
|
|
endforeach()
|
|
endif()
|
|
|
|
if(ARG_USES_YAMLCPP)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${YAMLCPP_INCLUDE_DIRS}")
|
|
target_link_libraries("${NAME}" ${YAMLCPP_LIBRARIES})
|
|
endif()
|
|
|
|
if(ARG_USES_CAIRO)
|
|
target_include_directories("${NAME}" SYSTEM ${VISIBILITY}
|
|
"${CAIRO_INCLUDE_DIRS}")
|
|
target_link_libraries("${NAME}" ${CAIRO_LIBRARIES})
|
|
endif()
|
|
|
|
set_target_properties(${NAME} PROPERTIES
|
|
COMPILE_FLAGS ${TARGET_COMPILE_FLAGS})
|
|
|
|
# Add the binary directory first, so that port.h is included after it has
|
|
# been generated.
|
|
target_include_directories("${NAME}" ${VISIBILITY} "${CMAKE_BINARY_DIR}")
|
|
target_include_directories("${NAME}" ${VISIBILITY} "${CMAKE_SOURCE_DIR}")
|
|
|
|
foreach(DEPENDENCY ${ARG_DEPENDS})
|
|
target_link_libraries(${NAME} ${DEPENDENCY})
|
|
endforeach()
|
|
|
|
# Figure out where to install the header. The logic goes like this: either
|
|
# the header is in the current binary directory (i.e. generated, like port.h)
|
|
# or in the current source directory - a regular header. It could also
|
|
# already be absolute (i.e. generated through a google_proto_library rule).
|
|
# In all cases we want to install the right header under the right subtree,
|
|
# e.g. foo/bar/baz.h.in will be installed from the binary directory as
|
|
# 'include/foo/bar/baz.h'.
|
|
foreach(HDR ${ARG_HDRS})
|
|
if (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${HDR})
|
|
set(ABS_FIL "${CMAKE_CURRENT_BINARY_DIR}/${HDR}")
|
|
file(RELATIVE_PATH REL_FIL ${CMAKE_BINARY_DIR} ${ABS_FIL})
|
|
elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${HDR})
|
|
set(ABS_FIL "${CMAKE_CURRENT_SOURCE_DIR}/${HDR}")
|
|
file(RELATIVE_PATH REL_FIL ${CMAKE_SOURCE_DIR} ${ABS_FIL})
|
|
else()
|
|
set(ABS_FIL "${HDR}")
|
|
file(RELATIVE_PATH REL_FIL ${CMAKE_BINARY_DIR} ${ABS_FIL})
|
|
endif()
|
|
get_filename_component(INSTALL_DIR ${REL_FIL} DIRECTORY)
|
|
install(
|
|
FILES
|
|
${ABS_FIL}
|
|
DESTINATION
|
|
include/${INSTALL_DIR}
|
|
)
|
|
endforeach()
|
|
endmacro(_common_compile_stuff)
|
|
|
|
# Create a static library out of other static libraries by running a GNU ar
|
|
# script over the dependencies.
|
|
function(google_combined_library NAME)
|
|
set(MULTI_VALUE_ARGS SRCS)
|
|
cmake_parse_arguments(ARG "" "" "${MULTI_VALUE_ARGS}" ${ARGN})
|
|
|
|
# Cmake requires a source file for each library, so we create a dummy file
|
|
# that is empty. Its creation depends on all libraries we want to include in
|
|
# our combined static library, i.e. it will be touched whenever any of them
|
|
# change, which means that our combined library is regenerated.
|
|
set(DUMMY_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_dummy.cc)
|
|
add_custom_command(
|
|
OUTPUT ${DUMMY_SOURCE}
|
|
COMMAND cmake -E touch ${DUMMY_SOURCE}
|
|
DEPENDS ${ARG_SRCS}
|
|
)
|
|
|
|
# Just a dummy library, we will overwrite its output directly after again
|
|
# with its POST_BUILD step.
|
|
google_library(${NAME}
|
|
SRCS ${DUMMY_SOURCE}
|
|
DEPENDS ${ARG_SRCS}
|
|
)
|
|
|
|
# We will delete the static lib generated by the last call to
|
|
# 'google_library' and recreate it using a GNU ar script that combines the
|
|
# SRCS into the NAME.
|
|
# TODO(hrapp): this is probably not very portable, but should work fine on
|
|
# Linux.
|
|
set(AR_SCRIPT "")
|
|
set(AR_SCRIPT "CREATE $<TARGET_FILE:${NAME}>\n")
|
|
foreach(SRC ${ARG_SRCS})
|
|
set(AR_SCRIPT "${AR_SCRIPT}ADDLIB $<TARGET_FILE:${SRC}>\n")
|
|
endforeach()
|
|
set(AR_SCRIPT "${AR_SCRIPT}SAVE\nEND\n")
|
|
set(AR_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${NAME}_ar.script")
|
|
file(GENERATE OUTPUT ${AR_SCRIPT_FILE} CONTENT ${AR_SCRIPT})
|
|
|
|
add_custom_command(TARGET ${NAME} POST_BUILD
|
|
COMMAND rm $<TARGET_FILE:${NAME}>
|
|
COMMAND ${CMAKE_AR}
|
|
ARGS -M < ${AR_SCRIPT_FILE}
|
|
COMMENT "Recombining static libraries into ${NAME}."
|
|
)
|
|
endfunction()
|
|
|
|
# Create a variable 'VAR_NAME'='FLAG'. If VAR_NAME is already set, FLAG is
|
|
# appended.
|
|
function(google_add_flag VAR_NAME FLAG)
|
|
if (${VAR_NAME})
|
|
set(${VAR_NAME} "${${VAR_NAME}} ${FLAG}" PARENT_SCOPE)
|
|
else()
|
|
set(${VAR_NAME} "${FLAG}" PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
|
|
macro(_common_test_stuff)
|
|
add_executable(${NAME}
|
|
${ARG_SRCS} ${ARG_HDRS}
|
|
)
|
|
_common_compile_stuff("PRIVATE")
|
|
|
|
# Make sure that gmock always includes the correct gtest/gtest.h.
|
|
target_include_directories("${NAME}" SYSTEM PRIVATE
|
|
"${GMOCK_SRC_DIR}/gtest/include")
|
|
target_link_libraries("${NAME}" gmock_main)
|
|
endmacro()
|
|
|
|
function(google_catkin_test NAME)
|
|
if(NOT "${CATKIN_ENABLE_TESTING}")
|
|
return()
|
|
endif()
|
|
|
|
_parse_arguments("${ARGN}")
|
|
_common_test_stuff()
|
|
|
|
# Copied from the catkin sources. Tracked in ros/catkin:#830.
|
|
add_dependencies(tests ${NAME})
|
|
get_target_property(_target_path ${NAME} RUNTIME_OUTPUT_DIRECTORY)
|
|
set(cmd "${_target_path}/${NAME} --gtest_output=xml:${CATKIN_TEST_RESULTS_DIR}/${PROJECT_NAME}/gtest-${NAME}.xml")
|
|
catkin_run_tests_target("gtest" ${NAME} "gtest-${NAME}.xml"
|
|
COMMAND ${cmd}
|
|
DEPENDENCIES ${NAME}
|
|
WORKING_DIRECTORY ${ARG_WORKING_DIRECTORY})
|
|
endfunction()
|
|
|
|
function(google_test NAME)
|
|
_parse_arguments("${ARGN}")
|
|
_common_test_stuff()
|
|
add_test(${NAME} ${NAME})
|
|
endfunction()
|
|
|
|
function(google_binary NAME)
|
|
_parse_arguments("${ARGN}")
|
|
|
|
add_executable(${NAME}
|
|
${ARG_SRCS} ${ARG_HDRS}
|
|
)
|
|
|
|
_common_compile_stuff("PRIVATE")
|
|
|
|
install(TARGETS "${NAME}" RUNTIME DESTINATION bin)
|
|
endfunction()
|
|
|
|
function(google_library NAME)
|
|
_parse_arguments("${ARGN}")
|
|
|
|
add_library(${NAME}
|
|
STATIC
|
|
${ARG_SRCS} ${ARG_HDRS}
|
|
)
|
|
set_property(TARGET "${NAME}" PROPERTY POSITION_INDEPENDENT_CODE ON)
|
|
|
|
# Update the global variable that contains all static libraries.
|
|
SET(ALL_LIBRARIES "${ALL_LIBRARIES};${NAME}" CACHE INTERNAL "ALL_LIBRARIES")
|
|
|
|
# This is needed for header only libraries. While they do not really mean
|
|
# anything for cmake, they are useful to make dependencies explicit.
|
|
set_target_properties(${NAME} PROPERTIES LINKER_LANGUAGE CXX)
|
|
|
|
_common_compile_stuff("PUBLIC")
|
|
endfunction()
|
|
|
|
function(google_proto_library NAME)
|
|
_parse_arguments("${ARGN}")
|
|
|
|
set(PROTO_SRCS)
|
|
set(PROTO_HDRS)
|
|
foreach(FIL ${ARG_SRCS})
|
|
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
|
|
get_filename_component(FIL_WE ${FIL} NAME_WE)
|
|
get_filename_component(FIL_NAME ${FIL} NAME)
|
|
|
|
list(APPEND PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
|
|
list(APPEND PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
|
|
|
|
add_custom_command(
|
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
|
|
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
|
|
ARGS --cpp_out ${CMAKE_BINARY_DIR} -I
|
|
${CMAKE_SOURCE_DIR} ${ABS_FIL}
|
|
DEPENDS ${ABS_FIL}
|
|
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
|
|
VERBATIM
|
|
)
|
|
endforeach()
|
|
|
|
set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS}
|
|
PROPERTIES GENERATED TRUE)
|
|
|
|
google_library("${NAME}"
|
|
SRCS "${PROTO_SRCS}"
|
|
HDRS "${PROTO_HDRS}"
|
|
DEPENDS "${ARG_DEPENDS}"
|
|
)
|
|
|
|
target_include_directories("${NAME}" SYSTEM "PUBLIC"
|
|
"${PROTOBUF_INCLUDE_DIR}")
|
|
# TODO(hrapp): This should not explicityly list pthread and use
|
|
# PROTOBUF_LIBRARIES, but that failed on first try.
|
|
target_link_libraries("${NAME}" ${PROTOBUF_LIBRARY} pthread)
|
|
endfunction()
|
|
|
|
macro(google_initialize_cartographer_project)
|
|
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
|
set(GOOG_CXX_FLAGS "-pthread -std=c++11 ${GOOG_CXX_FLAGS}")
|
|
|
|
google_add_flag(GOOG_CXX_FLAGS "-Wall")
|
|
google_add_flag(GOOG_CXX_FLAGS "-Wpedantic")
|
|
|
|
# Turn some warnings into errors.
|
|
google_add_flag(GOOG_CXX_FLAGS "-Werror=format-security")
|
|
google_add_flag(GOOG_CXX_FLAGS "-Werror=missing-braces")
|
|
google_add_flag(GOOG_CXX_FLAGS "-Werror=reorder")
|
|
google_add_flag(GOOG_CXX_FLAGS "-Werror=return-type")
|
|
google_add_flag(GOOG_CXX_FLAGS "-Werror=uninitialized")
|
|
|
|
if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
|
|
set(CMAKE_BUILD_TYPE Release)
|
|
endif()
|
|
|
|
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
|
google_add_flag(GOOG_CXX_FLAGS "-O3 -DNDEBUG")
|
|
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
|
google_add_flag(GOOG_CXX_FLAGS "-O3 -g -DNDEBUG")
|
|
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
message(FATAL_ERROR "Compiling in debug mode is not supported.")
|
|
else()
|
|
message(FATAL_ERROR "Unknown CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
|
|
endif()
|
|
|
|
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
|
|
|
endmacro()
|
|
|
|
macro(google_enable_testing)
|
|
set(GMOCK_SRC_DIR "/usr/src/gmock" CACHE STRING "Path to google-mock sources.")
|
|
add_subdirectory(${GMOCK_SRC_DIR} "${CMAKE_CURRENT_BINARY_DIR}/gmock")
|
|
enable_testing()
|
|
endmacro()
|