Iput子系统探究--1(input_dev)

本文详细介绍了Linux输入子系统的初始化过程、input设备的数据结构及如何分配、注册设备等内容。通过剖析核心代码,帮助读者理解input子系统的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



1.input子系统初始化

input子系统对上层应用提供一个统一的接口--字符设备接口-主设备号13

static const struct file_operations input_fops = {
 .owner = THIS_MODULE,
 .open = input_open_file,
 .llseek = noop_llseek,
};

static int __init input_init(void)
{
 int err;

 err = class_register(&input_class); /*注册input设备类*/

 err = input_proc_init();   /*初始化input_proc*/
 

 err = register_chrdev(INPUT_MAJOR, "input", &input_fops);/*注册input字符设备*/
 
}


2.关于input设备
2.1 设备的数据结构
 
/**
 * struct input_dev - represents an input device
 * @name: name of the device
 * @id: id of the device (struct input_id)
 
 * @evbit: bitmap of types of events supported by the device (EV_KEY,
 * EV_REL, etc.)
 * @keybit: bitmap of keys/buttons this device has
 * @relbit: bitmap of relative axes for the device
 * @absbit: bitmap of absolute axes for the device
 * @mscbit: bitmap of miscellaneous events supported by the device
 * @ledbit: bitmap of leds present on the device
 * @sndbit: bitmap of sound effects supported by the device
 * @ffbit: bitmap of force feedback effects supported by the device
 * @swbit: bitmap of switches present on the device

 * @keycodemax: size of keycode table
 * @keycodesize: size of elements in keycode table
 * @keycode: map of scancodes to keycodes for this device
 * @getkeycode: optional legacy method to retrieve current keymap.
 * @setkeycode: optional method to alter current keymap, used to implement
 * sparse keymaps. If not supplied default mechanism will be used.
 * The method is being called while holding event_lock and thus must
 * not sleep
 * @getkeycode_new: transition method
 * @setkeycode_new: transition method
 
 * @repeat_key: stores key code of the last key pressed; used to implement
 * software autorepeat
 * @open: this method is called when the very first user calls
 * input_open_device(). The driver must prepare the device
 * to start generating events (start polling thread,
 * request an IRQ, submit URB, etc.)
 *
 * @event: event handler for events sent _to_ the device, like EV_LED
 * or EV_SND. The device is expected to carry out the requested
 * action (turn on a LED, play sound, etc.) The call is protected
 * by @event_lock and must not sleep
 
 * @grab: input handle that currently has the device grabbed (via
 * EVIOCGRAB ioctl). When a handle grabs a device it becomes sole
 * recipient for all input events coming from the device
 
 * @event_lock: this spinlock is is taken when input core receives
 * and processes a new event for the device (in input_event()).
 * Code that accesses and/or modifies parameters of a device
 * (such as keymap or absmin, absmax, absfuzz, etc.) after device
 * has been registered with input core must take this lock.
 
 * @mutex: serializes calls to open(), close() and flush() methods-->互斥访问
 
 * @sync: set to %true when there were no new events since last EV_SYN
 * @dev: driver model's view of this device
 * @h_list: list of input handles associated with the device. When
 * accessing the list dev->mutex must be held
 * @node: used to place the device onto input_dev_list
 */
 
//#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))  -->nr/ 32
struct input_dev {
 const char *name;
 struct input_id id;

 unsigned long evbit[BITS_TO_LONGS(EV_CNT)];     //evbit[1]; -->事件类型
 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];   //keybit[24];-->按键
 unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; //relbie[1] 
 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; 
 unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
 unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
 unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
 unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
 unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

 unsigned int keycodemax;
 unsigned int keycodesize;
 void *keycode;

 int (*setkeycode)(struct input_dev *dev,
     unsigned int scancode, unsigned int keycode);
 int (*getkeycode)(struct input_dev *dev,
     unsigned int scancode, unsigned int *keycode);
 int (*setkeycode_new)(struct input_dev *dev,
         const struct input_keymap_entry *ke,
         unsigned int *old_keycode);
 int (*getkeycode_new)(struct input_dev *dev,
         struct input_keymap_entry *ke);


 unsigned int repeat_key;
 struct timer_list timer;

 int rep[REP_CNT];

 
 unsigned long key[BITS_TO_LONGS(KEY_CNT)];
 unsigned long led[BITS_TO_LONGS(LED_CNT)];
 unsigned long snd[BITS_TO_LONGS(SND_CNT)];
 unsigned long sw[BITS_TO_LONGS(SW_CNT)];

 int (*open)(struct input_dev *dev);
 void (*close)(struct input_dev *dev);
 int (*flush)(struct input_dev *dev, struct file *file);
 int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);

 struct input_handle __rcu *grab;

 spinlock_t event_lock;
 struct mutex mutex;

 bool sync;

 struct device dev;

 /*h_list: list of input handles associated with the device*/
 struct list_head h_list;
 
 /*node: used to place the device onto input_dev_list*/
 struct list_head node;
};
2.2 分配设备-->
struct input_dev *input_allocate_device(void)
{
 struct input_dev *dev;

 dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
 
 if (dev) {
  
  dev->dev.type = &input_dev_type;  /*设置device_type*/
  
  dev->dev.class = &input_class;   /*设置设备类*/
  
  device_initialize(&dev->dev);   /*初始化设备*/
   
  mutex_init(&dev->mutex);    /*初始化mutex*/
  
  spin_lock_init(&dev->event_lock);  /*初始化自旋锁*/
  
  /*h_list: list of input handles associated with the device*/
  INIT_LIST_HEAD(&dev->h_list);   
  
  /*node: used to place the device onto input_dev_list*/
  INIT_LIST_HEAD(&dev->node);    

  __module_get(THIS_MODULE);
 }

 return dev;
}

2.3 注册设备
{
 static atomic_t input_no = ATOMIC_INIT(0);
 struct input_handler *handler;
 const char *path;
 int error;

 /* Every input device generates EV_SYN/SYN_REPORT events. */
 __set_bit(EV_SYN, dev->evbit);

 /* KEY_RESERVED is not supposed to be transmitted to userspace. */
 __clear_bit(KEY_RESERVED, dev->keybit);


 /*
  * If delay and period are pre-set by the driver, then autorepeating
  * is handled by the driver itself and we don't do it in input.c.
  */
 init_timer(&dev->timer);
 if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
  dev->timer.data = (long) dev;
  dev->timer.function = input_repeat_key;
  dev->rep[REP_DELAY] = 250;
  dev->rep[REP_PERIOD] = 33;
 }

 if (!dev->getkeycode && !dev->getkeycode_new)
  dev->getkeycode_new = input_default_getkeycode;

 if (!dev->setkeycode && !dev->setkeycode_new)
  dev->setkeycode_new = input_default_setkeycode;

 dev_set_name(&dev->dev, "input%ld",       /*设备名字input%ld*/
       (unsigned long) atomic_inc_return(&input_no) - 1);

 error = device_add(&dev->dev);     /*添加设备--->设备驱动模型中讲过*/
 
 error = mutex_lock_interruptible(&input_mutex); /*保证互资源斥访问共享*/

 list_add_tail(&dev->node, &input_dev_list);  /*将设备添加到全局的input_dev_list设备链表中*/

 /*handler_list是handler链表(处在事件层,是内核已经实现好的,不需要驱动程序员实现--evdev,misc等) 
 */
 list_for_each_entry(handler, &input_handler_list, node)
  input_attach_handler(dev, handler);         /*下面分析*/  

 mutex_unlock(&input_mutex);

 return 0;
}

/*************************接下来分析input_attach_handler()***************************/

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
 const struct input_device_id *id;
 int error;

 id = input_match_device(handler, dev);    //判断input_dev设备和handler是否相匹配
 if (!id)
  return -ENODEV;

 error = handler->connect(handler, dev, id);    //取得handler的connect函数(以evdev为例--按键/触屏等handler)
 if (error && error != -ENODEV)
  pr_err("failed to attach handler %s to device %s, error: %d\n",
         handler->name, kobject_name(&dev->dev.kobj), error);

 return error;
}

2.4 接下来分析handler->connect()

/*在分析之前首先先对handler有个认识,handler是内核已经帮我们实现好的,
 如mousedev,evdev,joydev,键盘等驱动,不需要我们去写*/
/*设备驱动程序员关心的是input_dev层面的....*/

-- ROMFS: Adding boards/px4/fmu-v5/extras/px4_io-v2_default.bin -> /etc/extras/px4_io-v2_default.bin -- Configuring done -- Generating done -- Build files have been written to: /home/me/下载/px4-autopilot-1.15.4/build/px4_fmu-v5_default [1/1299] Generating git version header FAILED: src/lib/version/build_git_version.h cd /home/me/下载/px4-autopilot-1.15.4 && /usr/bin/python3 /home/me/下载/px4-autopilot-1.15.4/src/lib/version/px_update_git_header.py /home/me/下载/px4-autopilot-1.15.4/build/px4_fmu-v5_default/src/lib/version/build_git_version.h --validate Error: the git tag 'c49f4c2142' does not match the expected format. The expected format is 'v<PX4 version>[-<custom version>]' <PX4 version>: v<major>.<minor>.<patch>[-rc<rc>|-beta<beta>|-alpha<alpha>|-dev] <custom version>: <major>.<minor>.<patch>[-rc<rc>|-beta<beta>|-alpha<alpha>|-dev] Examples: v1.9.0-rc3 (preferred) v1.9.0-beta1 v1.9.0-1.0.0 v1.9.0-1.0.0-alpha2 See also https://docs.px4.io/main/en/dev_setup/building_px4.html#building-for-nuttx [2/1299] Generating ../../../platforms/nuttx/NuttX/nuttx/.config ninja: build stopped: subcommand failed. make: *** [Makefile:227:px4_fmu-v5_default] 错误 1如何修改代码避免此错误############################################################################ # # Copyright (c) 2017 - 2024 PX4 Development Team. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. 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. # 3. Neither the name PX4 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. # ############################################################################ #============================================================================= # CMAKE CODING STANDARD FOR PX4 # # Structure # --------------------------------------------------------------------------- # # * Common functions should be included in px_base.cmake. # # * OS/ board specific fucntions should be include in # px_impl_${PX4_PLATFORM}.cmake # # Formatting # --------------------------------------------------------------------------- # # * Use hard indents to match the px4 source code. # # * All function and script arguments are upper case. # # * All local variables are lower case. # # * All cmake functions are lowercase. # # * For else, endif, endfunction, etc, never put the name of the statement # # Functions/Macros # --------------------------------------------------------------------------- # # * Use px4_parse_function_args to parse functions and check for required # arguments. Unless there is only one argument in the function and it is clear. # # * Never use macros. They allow overwriting global variables and this # makes variable declarations hard to locate. # # * If a target from add_custom_* is set in a function, explicitly pass it # as an output argument so that the target name is clear to the user. # # * Avoid use of global variables in functions. Functions in a nested # scope may use global variables, but this makes it difficult to # reuse functions. # # Included CMake Files # --------------------------------------------------------------------------- # # * All variables in config files must have the prefix "config_". # # * Never set global variables in an included cmake file, # you may only define functions. This excludes config and Toolchain files. # This makes it clear to the user when variables are being set or targets # are being created. # # * Setting a global variable in a CMakeLists.txt file is ok, because # each CMakeLists.txt file has scope in the current directory and all # subdirectories, so it is not truly global. # # * All toolchain files should be included in the cmake # directory and named Toolchain-"name".cmake. # # Misc # --------------------------------------------------------------------------- # # * If referencing a string variable, don't put it in quotes. # Don't do "${PX4_PLATFORM}" STREQUAL "posix", # instead type ${PX4_PLATFORM} STREQUAL "posix". This will throw an # error when ${PX4_PLATFORM} is not defined instead of silently # evaluating to false. # #============================================================================= cmake_minimum_required(VERSION 3.9 FATAL_ERROR) set(PX4_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE FILEPATH "PX4 source directory" FORCE) set(PX4_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE FILEPATH "PX4 binary directory" FORCE) list(APPEND CMAKE_MODULE_PATH ${PX4_SOURCE_DIR}/cmake) include(px4_parse_function_args) #============================================================================= # git # include(px4_git) execute_process( COMMAND git describe --exclude ext/* --always --tags OUTPUT_VARIABLE PX4_GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${PX4_SOURCE_DIR} ) set(PX4_GIT_TAG "v1.15.4") # git describe to X.Y.Z version string(REPLACE "." ";" VERSION_LIST ${PX4_GIT_TAG}) # major version list(GET VERSION_LIST 0 PX4_VERSION_MAJOR) string(REPLACE "v" "" PX4_VERSION_MAJOR ${PX4_VERSION_MAJOR}) # minor version list(GET VERSION_LIST 1 PX4_VERSION_MINOR) # patch version list(GET VERSION_LIST 2 PX4_VERSION_PATCH) string(REPLACE "-" ";" PX4_VERSION_PATCH ${PX4_VERSION_PATCH}) list(GET PX4_VERSION_PATCH 0 PX4_VERSION_PATCH) # # Capture only the hash part after 'g' string(REGEX MATCH "g([a-f0-9]+)$" GIT_HASH "${PX4_GIT_TAG}") set(PX4_GIT_HASH ${CMAKE_MATCH_1}) define_property(GLOBAL PROPERTY PX4_MODULE_LIBRARIES BRIEF_DOCS "PX4 module libs" FULL_DOCS "List of all PX4 module libraries" ) define_property(GLOBAL PROPERTY PX4_KERNEL_MODULE_LIBRARIES BRIEF_DOCS "PX4 kernel side module libs" FULL_DOCS "List of all PX4 kernel module libraries" ) define_property(GLOBAL PROPERTY PX4_MODULE_PATHS BRIEF_DOCS "PX4 module paths" FULL_DOCS "List of paths to all PX4 modules" ) define_property(GLOBAL PROPERTY PX4_SRC_FILES BRIEF_DOCS "src files from all PX4 modules & libs" FULL_DOCS "SRC files from px4_add_{module,library}" ) #============================================================================= # configuration # include(px4_add_module) set(config_module_list) set(config_kernel_list) # Find Python find_package(PythonInterp 3) # We have a custom error message to tell users how to install python3. if(NOT PYTHONINTERP_FOUND) message(FATAL_ERROR "Python 3 not found. Please install Python 3:\n" " Ubuntu: sudo apt install python3 python3-dev python3-pip\n" " macOS: brew install python") endif() option(PYTHON_COVERAGE "Python code coverage" OFF) if(PYTHON_COVERAGE) message(STATUS "python coverage enabled") set(PYTHON_EXECUTABLE coverage run -p) endif() include(px4_config) include(kconfig) message(STATUS "PX4 config: ${PX4_CONFIG}") message(STATUS "PX4 platform: ${PX4_PLATFORM}") if($ENV{CLION_IDE}) # CLion automatically executes some compiler commands after configuring the # project. This would fail on NuttX, as visibility.h tries to (indirectly) # include nuttx/config.h, which at that point does not exist yet add_definitions(-DPX4_DISABLE_GCC_POISON) endif() if(${PX4_PLATFORM} STREQUAL "posix") if(ENABLE_LOCKSTEP_SCHEDULER) add_definitions(-DENABLE_LOCKSTEP_SCHEDULER) message(STATUS "PX4 lockstep: enabled") else() message(STATUS "PX4 lockstep: disabled") endif() endif() # external modules set(EXTERNAL_MODULES_LOCATION "" CACHE STRING "External modules source location") if(NOT EXTERNAL_MODULES_LOCATION STREQUAL "") get_filename_component(EXTERNAL_MODULES_LOCATION "${EXTERNAL_MODULES_LOCATION}" ABSOLUTE) endif() set_property(GLOBAL PROPERTY PX4_MODULE_CONFIG_FILES) include(platforms/${PX4_PLATFORM}/cmake/px4_impl_os.cmake) list(APPEND CMAKE_MODULE_PATH ${PX4_SOURCE_DIR}/platforms/${PX4_PLATFORM}/cmake) if(EXISTS "${PX4_SOURCE_DIR}/platforms/${PX4_PLATFORM}/cmake/init.cmake") include(init) endif() #============================================================================= # project definition # project(px4 CXX C ASM) # CMake build type (Debug Release RelWithDebInfo MinSizeRel Coverage) if(NOT CMAKE_BUILD_TYPE) if(${PX4_PLATFORM} STREQUAL "nuttx") set(PX4_BUILD_TYPE "MinSizeRel") else() set(PX4_BUILD_TYPE "RelWithDebInfo") endif() set(CMAKE_BUILD_TYPE ${PX4_BUILD_TYPE} CACHE STRING "Build type" FORCE) endif() if((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "Coverage")) set(MAX_CUSTOM_OPT_LEVEL -O0) elseif(CMAKE_BUILD_TYPE MATCHES "Sanitizer") set(MAX_CUSTOM_OPT_LEVEL -O1) elseif(CMAKE_BUILD_TYPE MATCHES "Release") set(MAX_CUSTOM_OPT_LEVEL -O3) else() if(px4_constrained_flash_build) set(MAX_CUSTOM_OPT_LEVEL -Os) else() set(MAX_CUSTOM_OPT_LEVEL -O2) endif() endif() set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel;Coverage;AddressSanitizer;UndefinedBehaviorSanitizer") message(STATUS "cmake build type: ${CMAKE_BUILD_TYPE}") # Check if LTO option and check if toolchain supports it if(LTO) include(CheckIPOSupported) check_ipo_supported() message(AUTHOR_WARNING "LTO enabled: LTO is highly experimental and should not be used in production") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) endif() set(package-contact "px4users@googlegroups.com") set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PX4_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PX4_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PX4_BINARY_DIR}) #============================================================================= # gold linker - use if available (posix only for now) if(${PX4_PLATFORM} STREQUAL "posix") include(CMakeDependentOption) CMAKE_DEPENDENT_OPTION(USE_LD_GOLD "Use GNU gold linker" ON "NOT WIN32;NOT APPLE" OFF ) if(USE_LD_GOLD) execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) if("${LD_VERSION}" MATCHES "GNU gold") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold") else() set(USE_LD_GOLD OFF) endif() endif() endif() #============================================================================= # Setup install paths if(${PX4_PLATFORM} STREQUAL "posix") # This makes it possible to dynamically load code which depends on symbols # inside the px4 executable. set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_ENABLE_EXPORTS ON) if(CMAKE_BUILD_TYPE MATCHES "Coverage") include(coverage) endif() include(sanitizers) # Define GNU standard installation directories include(GNUInstallDirs) if (NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Install path prefix" FORCE) endif() endif() include(ccache) #============================================================================= # get chip and chip manufacturer # px4_os_determine_build_chip() if(NOT PX4_CHIP_MANUFACTURER) message(FATAL_ERROR "px4_os_determine_build_chip() needs to set PX4_CHIP_MANUFACTURER") endif() if(NOT PX4_CHIP) message(FATAL_ERROR "px4_os_determine_build_chip() needs to set PX4_CHIP") endif() #============================================================================= # build flags # include(px4_add_common_flags) px4_add_common_flags() px4_os_add_flags() #============================================================================= # board cmake init (optional) # if(EXISTS ${PX4_BOARD_DIR}/cmake/init.cmake) include(${PX4_BOARD_DIR}/cmake/init.cmake) endif() #============================================================================= # message, and airframe generation # include(px4_metadata) add_subdirectory(msg EXCLUDE_FROM_ALL) px4_generate_airframes_xml(BOARD ${PX4_BOARD}) #============================================================================= # external projects # set(ep_base ${PX4_BINARY_DIR}/external) set_property(DIRECTORY PROPERTY EP_BASE ${ep_base}) # add external project install folders to build # add the directories so cmake won't warn execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}/Install) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}/Install/lib) link_directories(${ep_base}/Install/lib) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}/Install/include) include_directories(${ep_base}/Install/include) #============================================================================= # external modules # set(external_module_paths) if (NOT EXTERNAL_MODULES_LOCATION STREQUAL "") message(STATUS "External modules: ${EXTERNAL_MODULES_LOCATION}") add_subdirectory("${EXTERNAL_MODULES_LOCATION}/src" external_modules) foreach(external_module ${config_module_list_external}) add_subdirectory(${EXTERNAL_MODULES_LOCATION}/src/${external_module} external_modules/${external_module}) list(APPEND external_module_paths ${EXTERNAL_MODULES_LOCATION}/src/${external_module}) endforeach() endif() #============================================================================= # Testing - Automatic unit and integration testing with CTest # # optionally enable cmake testing (supported only on posix) option(CMAKE_TESTING "Configure test targets" OFF) if(${PX4_CONFIG} STREQUAL "px4_sitl_test") set(CMAKE_TESTING ON) endif() if(CMAKE_TESTING) include(CTest) # sets BUILD_TESTING variable endif() # enable test filtering to run only specific tests with the ctest -R regex functionality set(TESTFILTER "" CACHE STRING "Filter string for ctest to selectively only run specific tests (ctest -R)") # if testing is enabled download and configure gtest list(APPEND CMAKE_MODULE_PATH ${PX4_SOURCE_DIR}/cmake/gtest/) include(px4_add_gtest) if(BUILD_TESTING) include(gtest) add_custom_target(test_results COMMAND GTEST_COLOR=1 ${CMAKE_CTEST_COMMAND} --output-on-failure -T Test -R ${TESTFILTER} USES_TERMINAL DEPENDS px4 examples__dyn_hello USES_TERMINAL COMMENT "Running tests" WORKING_DIRECTORY ${PX4_BINARY_DIR}) set_target_properties(test_results PROPERTIES EXCLUDE_FROM_ALL TRUE) endif() #============================================================================= # subdirectories # add_library(parameters_interface INTERFACE) add_library(kernel_parameters_interface INTERFACE) add_library(events_interface INTERFACE) add_library(kernel_events_interface INTERFACE) include(px4_add_library) add_subdirectory(src/lib EXCLUDE_FROM_ALL) add_subdirectory(platforms/${PX4_PLATFORM}/src/px4) add_subdirectory(platforms EXCLUDE_FROM_ALL) if(EXISTS "${PX4_BOARD_DIR}/CMakeLists.txt") add_subdirectory(${PX4_BOARD_DIR}) endif() foreach(module ${config_module_list}) add_subdirectory(src/${module}) endforeach() # add events lib after modules and libs as it needs to know all source files (PX4_SRC_FILES) add_subdirectory(src/lib/events EXCLUDE_FROM_ALL) # metadata needs PX4_MODULE_CONFIG_FILES add_subdirectory(src/lib/metadata EXCLUDE_FROM_ALL) # must be the last module before firmware add_subdirectory(src/lib/parameters EXCLUDE_FROM_ALL) if(${PX4_PLATFORM} STREQUAL "nuttx" AND NOT CONFIG_BUILD_FLAT) target_link_libraries(parameters_interface INTERFACE usr_parameters) target_link_libraries(kernel_parameters_interface INTERFACE parameters) target_link_libraries(events_interface INTERFACE usr_events) target_link_libraries(kernel_events_interface INTERFACE events) else() target_link_libraries(parameters_interface INTERFACE parameters) target_link_libraries(events_interface INTERFACE events) endif() # firmware added last to generate the builtin for included modules add_subdirectory(platforms/${PX4_PLATFORM}) #============================================================================= # uORB graph generation: add a custom target 'uorb_graph' # set(uorb_graph_config ${PX4_BOARD}) set(graph_module_list "") foreach(module ${config_module_list}) set(graph_module_list "${graph_module_list}" "--src-path" "src/${module}") endforeach() add_custom_command(OUTPUT ${uorb_graph_config} COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/Tools/uorb_graph/create.py ${graph_module_list} --src-path src/lib --merge-depends --exclude-path src/examples --exclude-path src/lib/parameters # FIXME: enable & fix --file ${PX4_SOURCE_DIR}/Tools/uorb_graph/graph_${uorb_graph_config} WORKING_DIRECTORY ${PX4_SOURCE_DIR} COMMENT "Generating uORB graph" ) add_custom_target(uorb_graph DEPENDS ${uorb_graph_config}) include(bloaty) include(doxygen) include(metadata) include(package) # install python requirements using configured python add_custom_target(install_python_requirements COMMAND ${PYTHON_EXECUTABLE} -m pip install --break-system-packages --requirement ${PX4_SOURCE_DIR}/Tools/setup/requirements.txt DEPENDS ${PX4_SOURCE_DIR}/Tools/setup/requirements.txt USES_TERMINAL ) if(EXISTS "${PX4_SOURCE_DIR}/platforms/${PX4_PLATFORM}/cmake/finalize.cmake") include(finalize) endif()
最新发布
08-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值