简单的概述
make 和 cmake 是linux/UNIX系统下广泛使用的构建编译规则工具,面对复杂庞大的工程,各种源文件和工具文件分布在工程目录下,如何组织和有序地编译和使用这些文件,显然也是一项复杂的任务。Makefile是直接地定义编译规则以及描述目标之间依赖关系。CMakeLists.txt虽然也是具有相同的功能,但是它是对Makefile的抽象化以便更容易地实现工程编译规则的编写。(想更具体了解cmake与make的关系,请google)
PX4下的Makefile
它只是对CMakeLists.txt的一个简单封装,真正定义PX4工程的编译规则由CMakeList.txt文件实现。
这个文件主要完成:
检查cmake版本3.2及以上和解析命令行参数
ifeq ($(wildcard .git),)
$(error YOU HAVE TO USE GIT TO DOWNLOAD THIS REPOSITORY. ABORTING.)
endif
CMAKE_VER := $(shell Tools/check_cmake.sh; echo $$?)
ifneq ($(CMAKE_VER),0)
$(warning Not a valid CMake version or CMake not installed.)
$(warning On Ubuntu 16.04, install or upgrade via:)
$(warning )
$(warning 3rd party PPA:)
$(warning sudo add-apt-repository ppa:george-edison55/cmake-3.x -y)
$(warning sudo apt-get update)
$(warning sudo apt-get install cmake)
$(warning )
$(warning Official website:)
$(warning wget https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.sh)
$(warning chmod +x cmake-3.4.3-Linux-x86_64.sh)
$(warning sudo mkdir /opt/cmake-3.4.3)
$(warning sudo ./cmake-3.4.3-Linux-x86_64.sh --prefix=/opt/cmake-3.4.3 --exclude-subdir)
$(warning export PATH=/opt/cmake-3.4.3/bin:$$PATH)
$(warning )
$(error Fatal)
endif
...
...
FIRST_ARG := $(firstword $(MAKECMDGOALS))
ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
...
...
定义配置目标以及解析cmake编译规则
define cmake-build
+@$(eval BUILD_DIR = $(SRC_DIR)/build_$@$(BUILD_DIR_SUFFIX))
+@if [ $(PX4_CMAKE_GENERATOR) = "Ninja" ] && [ -e $(BUILD_DIR)/Makefile ]; then rm -rf $(BUILD_DIR); fi
+@if [ ! -e $(BUILD_DIR)/CMakeCache.txt ]; then mkdir -p $(BUILD_DIR) && cd $(BUILD_DIR) && cmake .. -G$(PX4_CMAKE_GENERATOR) -DCONFIG=$(1) $(CMAKE_ARGS) || (cd .. && rm -rf $(BUILD_DIR)); fi
+@echo "PX4 CONFIG: $(BUILD_DIR)"
+@$(PX4_MAKE) -C "$(BUILD_DIR)" $(PX4_MAKE_ARGS) $(ARGS)
endef
...
...
ALL_CONFIG_TARGETS := $(basename $(shell find "$(SRC_DIR)/cmake/configs" ! -name '*_common*' ! -name '*_sdflight_*' -name '*.cmake' -print | sed -e 's:^.*/::' | sort))
NUTTX_CONFIG_TARGETS := $(patsubst nuttx_%,%,$(filter nuttx_%,$(ALL_CONFIG_TARGETS)))
$(ALL_CONFIG_TARGETS):
$(call cmake-build,$@)
$(NUTTX_CONFIG_TARGETS):
$(call cmake-build,nuttx_$@)
...
...
进入工程根目录,在终端输入make px4fmu-v2_default时, 将在工程根目录下创建build_px4fmu-v2_default目录,然后进入此目录执行cmake .. -G”Unix Makefiles” -DCONFIG=nuttx_px4fmu-v2_default命令来解析工程根目录下的CMakeLists.txt文件,因此在build_px4fmu-v2_default下形成整个工程的编译规则。
具体分析PX4工程的编译规则CMakeList.txt(以make px4fmu-v2_default为例)
设置基本变量与引入cmake模块
set(PX4_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(PX4_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
...
string(REPLACE "_" ";" config_args ${CONFIG})
list(GET config_args 0 OS)
list(GET config_args 1 BOARD)
list(GET config_args 2 LABEL)
set(target_name "${OS}-${BOARD}-${LABEL}")
...
list(APPEND CMAKE_MODULE_PATH "${PX4_SOURCE_DIR}/cmake")
message(STATUS "cmake module path: ${CMAKE_MODULE_PATH}")
set(config_module "configs/${CONFIG}")
include(${config_module})
...
检测自定义cmake函数有没有实现,没有的话输出致命错误,退出cmake
set(px4_required_interface
px4_os_prebuild_targets
px4_os_add_flags
)
foreach(cmd ${px4_required_interface})
if(NOT COMMAND ${cmd})
message(FATAL_ERROR "${config_module} must implement ${cmd}")
endif()
endforeach()
set(px4_required_config
config_module_list
)
foreach(conf ${px4_required_config})
if(NOT DEFINED ${conf})
message(FATAL_ERROR "cmake/${config_module} must define ${conf}")
endif()
endforeach()
...
set(required_variables
CMAKE_C_COMPILER_ID
)
foreach(var ${required_variables})
if (NOT ${var})
message(FATAL_ERROR "Toolchain/config must define ${var}")
endif()
endforeach()
...
添加git submodule目标,其实没有干什么具体事情。
px4_add_git_submodule(TARGET git_genmsg PATH "Tools/genmsg")
px4_add_git_submodule(TARGET git_gencpp PATH "Tools/gencpp")
px4_add_git_submodule(TARGET git_mavlink PATH "mavlink/include/mavlink/v1.0")
px4_add_git_submodule(TARGET git_gtest PATH "unittests/gtest")
px4_add_git_submodule(TARGET git_uavcan PATH "src/modules/uavcan/libuavcan")
px4_add_git_submodule(TARGET git_nuttx PATH "NuttX")
px4_add_git_submodule(TARGET git_driverframework PATH "src/lib/DriverFramework")
px4_add_git_submodule(TARGET git_ecl PATH "src/lib/ecl")
px4_add_git_submodule(TARGET git_jmavsim PATH "Tools/jMAVSim")
px4_add_git_submodule(TARGET git_gazebo PATH "Tools/sitl_gazebo")
px4_add_git_submodule(TARGET git_matrix PATH "src/lib/matrix")
px4_add_git_submodule(TARGET git_cmake_hexagon PATH "cmake/cmake_hexagon")
...
nuttx系统源码的配置及编译(很重要),后面单独地具体分析!
px4_os_prebuild_targets(OUT prebuild_targets
BOARD ${BOARD}
THREADS ${THREADS})
px4_os_add_flags(
BOARD ${BOARD}
C_FLAGS c_flags
CXX_FLAGS cxx_flags
OPTIMIZATION_FLAGS optimization_flags
EXE_LINKER_FLAGS exe_linker_flags
INCLUDE_DIRS include_dirs
LINK_DIRS link_dirs
DEFINITIONS definitions)
px4_join(OUT CMAKE_EXE_LINKER_FLAGS LIST "${exe_linker_flags}" GLUE " ")
px4_join(OUT CMAKE_C_FLAGS LIST "${c_flags};${optimization_flags}" GLUE " ")
px4_join(OUT CMAKE_CXX_FLAGS LIST "${cxx_flags};${optimization_flags}" GLUE " ")
include_directories(${include_dirs})
link_directories(${link_dirs})
add_definitions(${definitions})
...
msg目录下的ROS msg定义文件被处理成关于topic的C结构体和C++类定义与针对px4fmu-v2板子参数的处理
add_subdirectory(msg)
px4_generate_messages(TARGET msg_gen
MSG_FILES ${msg_files}
OS ${OS}
DEPENDS git_genmsg git_gencpp prebuild_targets
)
px4_generate_parameters_xml(OUT parameters.xml BOARD ${BOARD})
px4_generate_airframes_xml(OUT airframes.xml BOARD ${BOARD})
add_custom_target(xml_gen
DEPENDS parameters.xml airframes.xml)
...
处理src目录下各个子目录的CMakelist.txt,将生成各个子模块以组件方式构建PX4固件
set(module_libraries)
foreach(module ${config_module_list})
string(REGEX MATCH "^[./]" external_module ${module})
if(external_module)
STRING(REGEX REPLACE "//" "/" EXT_MODULE ${module})
STRING(REGEX REPLACE "/" "__" EXT_MODULE_PREFIX ${EXT_MODULE})
add_subdirectory(${module} ${PX4_BINARY_DIR}/${EXT_MODULE_PREFIX})
else()
add_subdirectory(src/${module})
endif()
px4_mangle_name(${module} mangled_name)
list(APPEND module_libraries ${mangled_name})
endforeach()
set(module_external_libraries "${module_external_libraries}" CACHE INTERNAL "module_external_libraries")
add_subdirectory(src/firmware/${OS})
...
px4io-v2的配置与编译规则
if (config_io_board)
add_subdirectory(src/modules/px4iofirmware)
endif()
...
手写CMakeLists.txt大致的流程图:
手写的整个工程目标的依赖关系图:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)