Preparing changes to use automatic CMakeFiles also in the ROS projects. (#48)

master
Holger Rapp 2016-10-12 17:03:46 +02:00 committed by GitHub
parent be813a06fe
commit 8f64860b5d
2 changed files with 51 additions and 33 deletions

View File

@ -16,22 +16,23 @@ include(CMakeParseArguments)
macro(_parse_arguments ARGS) macro(_parse_arguments ARGS)
set(OPTIONS set(OPTIONS
USES_BOOST
USES_CERES USES_CERES
USES_EIGEN USES_EIGEN
USES_GFLAGS
USES_GLOG
USES_GLOG USES_GLOG
USES_LUA USES_LUA
USES_BOOST
USES_WEBP USES_WEBP
USES_GLOG
USES_GFLAGS
) )
# Options only used by projects using Cartographers cmake files. # Options only used by projects using Cartographers cmake files.
list(APPEND OPTIONS list(APPEND OPTIONS
USES_CARTOGRAPHER USES_CARTOGRAPHER
USES_ROS
USES_ZLIB
USES_PCL USES_PCL
USES_ROS
USES_YAMLCPP
USES_ZLIB
) )
set(ONE_VALUE_ARG ) set(ONE_VALUE_ARG )
set(MULTI_VALUE_ARGS SRCS HDRS DEPENDS) set(MULTI_VALUE_ARGS SRCS HDRS DEPENDS)
@ -108,6 +109,10 @@ macro(_common_compile_stuff VISIBILITY)
endforeach() endforeach()
endif() endif()
if(ARG_USES_YAMLCPP)
target_link_libraries("${NAME}" yaml-cpp)
endif()
set_target_properties(${NAME} PROPERTIES set_target_properties(${NAME} PROPERTIES
COMPILE_FLAGS ${TARGET_COMPILE_FLAGS}) COMPILE_FLAGS ${TARGET_COMPILE_FLAGS})
@ -165,17 +170,6 @@ function(google_combined_library NAME)
DEPENDS ${ARG_SRCS} DEPENDS ${ARG_SRCS}
) )
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_BINARY_DIR} ${REWRITTEN_PROTO}
DEPENDS ${REWRITTEN_PROTO}
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
VERBATIM
)
# Just a dummy library, we will overwrite its output directly after again # Just a dummy library, we will overwrite its output directly after again
# with its POST_BUILD step. # with its POST_BUILD step.
google_library(${NAME} google_library(${NAME}
@ -273,6 +267,7 @@ function(google_library NAME)
STATIC STATIC
${ARG_SRCS} ${ARG_HDRS} ${ARG_SRCS} ${ARG_HDRS}
) )
set_property(TARGET "${NAME}" PROPERTY POSITION_INDEPENDENT_CODE ON)
# Update the global variable that contains all static libraries. # Update the global variable that contains all static libraries.
SET(ALL_LIBRARIES "${ALL_LIBRARIES};${NAME}" CACHE INTERNAL "ALL_LIBRARIES") SET(ALL_LIBRARIES "${ALL_LIBRARIES};${NAME}" CACHE INTERNAL "ALL_LIBRARIES")

View File

@ -19,6 +19,7 @@
import os import os
from os import path from os import path
import re import re
import argparse
def MakeRelative(filename, directory): def MakeRelative(filename, directory):
@ -72,20 +73,20 @@ class Target(object):
return "\n".join(lines) return "\n".join(lines)
def ExtractCartographerIncludes(source): def ExtractProjectIncludes(project_name, source):
"""Returns all locally included files.""" """Returns all locally included files."""
includes = set() includes = set()
for line in open(MaybeUseCmakeFile(source)): for line in open(MaybeUseCmakeFile(source)):
if source.endswith(".proto"): if source.endswith(".proto"):
match = re.match(r'^import "(cartographer/[^"]+)', line) match = re.match(r'^import "(' + project_name + r'/[^"]+)', line)
else: else:
match = re.match(r'^#include "(cartographer/[^"]+)"', line) match = re.match(r'^#include "(' + project_name + r'/[^"]+)"', line)
if match: if match:
includes.add(match.group(1)) includes.add(match.group(1))
return includes return includes
def ExtractUses(source): def ExtractUses(project_name, source):
"""Finds the options for the third_party libraries used.""" """Finds the options for the third_party libraries used."""
uses = set() uses = set()
for line in open(MaybeUseCmakeFile(source)): for line in open(MaybeUseCmakeFile(source)):
@ -99,10 +100,21 @@ def ExtractUses(source):
uses.add("USES_GLOG") uses.add("USES_GLOG")
if re.match(r'^#include "gflags/', line): if re.match(r'^#include "gflags/', line):
uses.add("USES_GFLAGS") uses.add("USES_GFLAGS")
if re.match(r"^#include <boost/", line): if re.match(r'^#include ["<]boost/', line):
uses.add("USES_BOOST") uses.add("USES_BOOST")
if re.match(r'^#include "webp/', line): if re.match(r'^#include ["<]webp/', line):
uses.add("USES_WEBP") uses.add("USES_WEBP")
if re.match(r'^#include ["<]pcl/', line):
uses.add("USES_PCL")
if re.match(r'^#include ["<]ros/', line):
uses.add("USES_ROS")
if re.match(r'^#include "[a-zA-Z]*_msgs/', line):
uses.add("USES_ROS")
if re.match(r'^#include ["<]yaml-cpp/', line):
uses.add("USES_YAMLCPP")
if project_name != "cartographer":
if re.match(r'^#include ["<]cartographer/', line):
uses.add("USES_CARTOGRAPHER")
return uses return uses
@ -130,13 +142,20 @@ def ReadFileWithoutGoogleTargets(filename):
yield line.rstrip() yield line.rstrip()
def ParseArgs():
p = argparse.ArgumentParser(
description="Automatically update cMakeFiles using build conventions.")
p.add_argument("root", type=str, help="Source directory.")
return p.parse_args()
def main(): def main():
root_directory = os.path.realpath( args = ParseArgs()
os.path.join(os.path.dirname(__file__), os.path.pardir, "cartographer"))
targets_by_src = {} targets_by_src = {}
targets = [] targets = []
base_directory = path.realpath(path.join(root_directory, path.pardir)) project_name = os.path.basename(args.root)
base_directory = path.realpath(path.join(args.root, path.pardir))
directories = set() directories = set()
def AddTarget(target_type, name, directory, srcs, hdrs): def AddTarget(target_type, name, directory, srcs, hdrs):
@ -152,14 +171,16 @@ def main():
targets_by_src[proto_stem + ".pb.cc"] = target targets_by_src[proto_stem + ".pb.cc"] = target
directories.add(directory) directories.add(directory)
for (directory, sources) in FindSourceFiles(root_directory): for (directory, sources) in FindSourceFiles(args.root):
module_name = path.relpath(directory, module_name = path.relpath(directory,
path.realpath(root_directory)).replace("/", "_") path.realpath(args.root)).replace("/", "_")
prepend_module_name = lambda s: (module_name + "_" + s) if module_name != "." else s
headers = set(fn for fn in sources if fn.endswith(".h")) headers = set(fn for fn in sources if fn.endswith(".h"))
sources -= headers sources -= headers
for h in sorted(headers): for h in sorted(headers):
srcs = [] srcs = []
name = module_name + "_" + path.basename(path.splitext(h)[0]) name = prepend_module_name(path.basename(path.splitext(h)[0]))
cc_file = path.splitext(h)[0] + ".cc" cc_file = path.splitext(h)[0] + ".cc"
if cc_file in sources: if cc_file in sources:
sources.remove(cc_file) sources.remove(cc_file)
@ -169,13 +190,13 @@ def main():
tests = set(fn for fn in sources if fn.endswith("_test.cc")) tests = set(fn for fn in sources if fn.endswith("_test.cc"))
sources -= tests sources -= tests
for c in sorted(tests): for c in sorted(tests):
name = module_name + "_" + path.basename(path.splitext(c)[0]) name = prepend_module_name(path.basename(path.splitext(c)[0]))
AddTarget("google_test", name, directory, [c], []) AddTarget("google_test", name, directory, [c], [])
protos = set(fn for fn in sources if fn.endswith(".proto")) protos = set(fn for fn in sources if fn.endswith(".proto"))
sources -= protos sources -= protos
for c in sorted(protos): for c in sorted(protos):
name = module_name + "_" + path.basename(path.splitext(c)[0]) name = prepend_module_name(path.basename(path.splitext(c)[0]))
AddTarget("google_proto_library", name, directory, [c], []) AddTarget("google_proto_library", name, directory, [c], [])
mains = set(fn for fn in sources if fn.endswith("_main.cc")) mains = set(fn for fn in sources if fn.endswith("_main.cc"))
@ -185,7 +206,7 @@ def main():
# 'cartographer' to distinguish them after installation. So, # 'cartographer' to distinguish them after installation. So,
# 'io/asset_writer_main.cc' will generate a binary called # 'io/asset_writer_main.cc' will generate a binary called
# 'cartographer_asset_writer'. # 'cartographer_asset_writer'.
name = 'cartographer_' + path.basename(path.splitext(c)[0][:-5]) name = "cartographer_" + path.basename(path.splitext(c)[0][:-5])
AddTarget("google_binary", name, directory, [c], []) AddTarget("google_binary", name, directory, [c], [])
assert (not sources), "Remaining sources without target: %s" % sources assert (not sources), "Remaining sources without target: %s" % sources
@ -195,12 +216,14 @@ def main():
targets_in_directory = [t for t in targets if t.directory == directory] targets_in_directory = [t for t in targets if t.directory == directory]
for target in targets_in_directory: for target in targets_in_directory:
for src in target.srcs + target.hdrs: for src in target.srcs + target.hdrs:
for header in ExtractCartographerIncludes(src): for header in ExtractProjectIncludes(project_name, src):
dependant = targets_by_src[header] dependant = targets_by_src[header]
if dependant.name == target.name: if dependant.name == target.name:
continue continue
target.depends.add(dependant.name) target.depends.add(dependant.name)
target.uses.update(ExtractUses(src)) target.uses.update(ExtractUses(project_name, src))
if target.type is "google_test" and "USES_ROS" in target.uses:
target.type = "google_catkin_test"
cmake_file = path.join(directory, "CMakeLists.txt") cmake_file = path.join(directory, "CMakeLists.txt")
lines = list(ReadFileWithoutGoogleTargets(cmake_file)) lines = list(ReadFileWithoutGoogleTargets(cmake_file))