Preparing changes to use automatic CMakeFiles also in the ROS projects. (#48)
parent
be813a06fe
commit
8f64860b5d
|
@ -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")
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue