286 lines
9.7 KiB
CMake
286 lines
9.7 KiB
CMake
function(_get_path_relation path1 path2 result)
|
||
# 初始值设置为 0,表示没有包含关系
|
||
set(${result} 0 PARENT_SCOPE)
|
||
# 判断 path2 是否包含 path1
|
||
string(FIND "${path2}" "${path1}" _idx)
|
||
if(_idx GREATER -1)
|
||
# 如果 path2 包含 path1,设置 result 为 2(path2 是父路径)
|
||
set(${result} 1 PARENT_SCOPE)
|
||
else()
|
||
# 如果没有包含关系,检查 path1 是否包含 path2
|
||
string(FIND "${path1}" "${path2}" _idx)
|
||
if(_idx GREATER -1)
|
||
# 如果 path1 包含 path2,设置 result 为 1(path1 是父路径)
|
||
set(${result} 2 PARENT_SCOPE)
|
||
endif()
|
||
endif()
|
||
endfunction()
|
||
|
||
|
||
# 写成宏是为了能直接修改 list_var 所代表的变量
|
||
macro(_handle_path_add list_var path)
|
||
# 创建一个列表用于记录需要删除的路径
|
||
set(need_remove_list)
|
||
set(need_add 1)
|
||
|
||
# 遍历列表中的路径,检查与新路径的包含关系
|
||
foreach(li ${${list_var}})
|
||
set(relation 0)
|
||
# 获取路径之间的包含关系
|
||
_get_path_relation(${path} ${li} relation)
|
||
if (relation EQUAL 2)
|
||
# 如果新路径是父路径,跳过添加
|
||
#message("${path} 被 ${li} 包含,跳过添加")
|
||
set(need_add 0)
|
||
break()
|
||
elseif (relation EQUAL 1)
|
||
# 如果新路径包含旧路径,记录旧路径需要移除
|
||
list(APPEND need_remove_list ${li})
|
||
#message(" ${li} 被 ${path} 包含,移除旧的路径 ${li}")
|
||
endif()
|
||
endforeach()
|
||
|
||
# 删除已标记的路径
|
||
foreach(remove_path ${need_remove_list})
|
||
list(REMOVE_ITEM ${list_var} ${remove_path})
|
||
#message("已从 ${list_var} 中删除路径:${remove_path}")
|
||
endforeach()
|
||
|
||
# 如果需要添加新路径,将其添加到列表
|
||
if (need_add)
|
||
list(APPEND ${list_var} ${path})
|
||
#message("将路径 ${path} 添加到 ${list_var}")
|
||
endif()
|
||
endmacro()
|
||
|
||
function(get_common_path list_var out_var)
|
||
# 空列表直接返回空
|
||
list(LENGTH ${list_var} _path_count)
|
||
if(_path_count EQUAL 0)
|
||
set(${out_var} "" PARENT_SCOPE)
|
||
return()
|
||
endif()
|
||
|
||
# 取第一个路径作为初始公共路径
|
||
list(GET ${list_var} 0 _first_path)
|
||
string(REPLACE "\\" "/" _first_path "${_first_path}")
|
||
|
||
# 检查路径是否以 / 开头
|
||
set(_has_leading_slash 0)
|
||
if("${_first_path}" MATCHES "^/.*")
|
||
set(_has_leading_slash 1)
|
||
endif()
|
||
|
||
# 将路径拆分为部分
|
||
string(REPLACE "/" ";" _common_parts "${_first_path}")
|
||
|
||
# 遍历所有路径
|
||
foreach(_path IN LISTS ${list_var})
|
||
string(REPLACE "\\" "/" _path_norm "${_path}")
|
||
string(REPLACE "/" ";" _cur_parts "${_path_norm}")
|
||
|
||
# 取两个列表的较小长度,避免越界
|
||
list(LENGTH _common_parts _len1)
|
||
list(LENGTH _cur_parts _len2)
|
||
|
||
if(_len1 LESS _len2)
|
||
set(_min_len ${_len1})
|
||
else()
|
||
set(_min_len ${_len2})
|
||
endif()
|
||
|
||
# 没有可比部分,直接公共路径为空
|
||
if(_min_len EQUAL 0)
|
||
set(_common_parts "")
|
||
break()
|
||
endif()
|
||
|
||
math(EXPR _stop "${_min_len} - 1")
|
||
|
||
set(_new_common_parts "")
|
||
foreach(_idx RANGE 0 ${_stop})
|
||
list(GET _common_parts ${_idx} _part1)
|
||
list(GET _cur_parts ${_idx} _part2)
|
||
|
||
if(_part1 STREQUAL _part2)
|
||
list(APPEND _new_common_parts "${_part1}")
|
||
else()
|
||
break()
|
||
endif()
|
||
endforeach()
|
||
|
||
set(_common_parts ${_new_common_parts})
|
||
|
||
# 已经没有公共部分了,提前结束
|
||
list(LENGTH _common_parts _common_len)
|
||
if(_common_len EQUAL 0)
|
||
break()
|
||
endif()
|
||
endforeach()
|
||
|
||
# 拼回路径
|
||
if(_common_parts)
|
||
list(JOIN _common_parts "/" _common_path)
|
||
else()
|
||
set(_common_path "")
|
||
endif()
|
||
|
||
# 如果原路径有前导 '/', 在拼接回路径时添加它
|
||
if(_has_leading_slash)
|
||
set(_common_path "/${_common_path}")
|
||
endif()
|
||
|
||
set(${out_var} "${_common_path}" PARENT_SCOPE)
|
||
endfunction()
|
||
|
||
|
||
|
||
# 目前是远程开发所以 无需把源码复制一遍 扫描到公共目录直接使用即可
|
||
function(_create_linux_driver_proj_ex driver_name _target_list_var_name_)
|
||
# 此函数用于安装源码 同时创建 component 也可加入到cpack 安装包里
|
||
__check_none_extr_params(${ARGC} "${ARGN}" "${ARGV}")
|
||
__bfs_traverse_targets(_dependency_list_ ${_target_list_var_name_} _relys_)
|
||
|
||
set(_top_level_dir_list)
|
||
|
||
|
||
# 计算出公共路径,以及要复制的文件
|
||
foreach (_rely_ ${_relys_})
|
||
get_property(_attach_include_list_ TARGET ${_rely_} PROPERTY _attach_include_list_)
|
||
foreach (_rely_dir_ ${_attach_include_list_})
|
||
get_filename_component(_base_name_ "${_rely_dir_}" NAME)
|
||
_handle_path_add(_top_level_dir_list ${_rely_dir_})
|
||
endforeach()
|
||
get_property(_attach_source_list_ TARGET ${_rely_} PROPERTY _attach_source_list_)
|
||
foreach (_rely_dir_ ${_attach_source_list_})
|
||
_handle_path_add(_top_level_dir_list ${_rely_dir_})
|
||
endforeach()
|
||
get_property(_attach_file_list_ TARGET ${_rely_} PROPERTY _attach_file_list_)
|
||
foreach (_rely_file_ ${_attach_file_list_})
|
||
_handle_path_add(_top_level_dir_list ${_rely_file_})
|
||
endforeach()
|
||
endforeach()
|
||
|
||
|
||
message("_top_level_dir_list: ${_top_level_dir_list}")
|
||
# 调用函数计算公共路径
|
||
set(common_path)
|
||
get_common_path(_top_level_dir_list common_path)
|
||
# 输出结果
|
||
message("公共路径: ${common_path}")
|
||
|
||
|
||
set(Makefile "# 基础模块指令\n")
|
||
foreach (_rely_ ${_relys_})
|
||
set(_rely_file_list_)
|
||
get_property(_attach_source_list_ TARGET ${_rely_} PROPERTY _attach_source_list_)
|
||
foreach (_rely_dir_ ${_attach_source_list_})
|
||
file(GLOB_RECURSE _cur_rely_file_list_ "${_rely_dir_}/*.c" "${_rely_dir_}/*.cpp" )
|
||
list(APPEND _rely_file_list_ ${_cur_rely_file_list_})
|
||
endforeach()
|
||
get_property(_attach_file_list_ TARGET ${_rely_} PROPERTY _attach_file_list_)
|
||
list(APPEND _rely_file_list_ ${_attach_file_list_})
|
||
#message("_rely_ 【${_rely_}】 attach_source_list:【${_attach_source_list_}】 attach_file_list【${_attach_file_list_}】 ")
|
||
set(rely_objs "objs_${_rely_} :=")
|
||
set(new_prefix "")
|
||
foreach (_rely_file_ ${_rely_file_list_})
|
||
file(RELATIVE_PATH _rel_path "${common_path}" "${_rely_file_}")
|
||
|
||
get_filename_component(_dir "${_rel_path}" DIRECTORY)
|
||
get_filename_component(_name "${_rel_path}" NAME_WLE)
|
||
|
||
if(_dir STREQUAL "")
|
||
set(_new_path "${new_prefix}${_name}.o")
|
||
else()
|
||
set(_new_path "${new_prefix}${_dir}/${_name}.o")
|
||
endif()
|
||
|
||
# message("src = ${_rely_file_}")
|
||
# message("dst = ${_new_path}")
|
||
#message(" ${_new_path}")
|
||
string(APPEND rely_objs " ${_new_path}")
|
||
endforeach()
|
||
string(APPEND Makefile "${rely_objs}\n")
|
||
endforeach()
|
||
|
||
|
||
string(APPEND Makefile "\n# 内核模块组合指令\n")
|
||
|
||
|
||
foreach(target ${${_target_list_var_name_}})
|
||
set(_temp_list_ ${target})
|
||
set(_cur_relys_)
|
||
# 获取单个目标的relys
|
||
__bfs_traverse_targets(_dependency_list_ _temp_list_ _cur_relys_)
|
||
set(target_name "ko_${target}")
|
||
string(APPEND Makefile "obj-m += ${target_name}.o\n")
|
||
|
||
set(cur_target "${target_name}-y := ")
|
||
foreach(cur_rely ${_cur_relys_})
|
||
string(APPEND cur_target " $(objs_${cur_rely})")
|
||
endforeach()
|
||
message("${target} cur_relys ${_cur_relys_}")
|
||
string(APPEND Makefile "${cur_target}\n")
|
||
endforeach()
|
||
|
||
string(APPEND Makefile "\n# 综合指令")
|
||
string(APPEND Makefile "
|
||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||
MKFILE_DIR := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
|
||
OUT := $(MKFILE_DIR)/out
|
||
|
||
all:
|
||
mkdir -p $(OUT)
|
||
$(MAKE) -C $(KDIR) M=$(MKFILE_DIR) MO=$(OUT) V=1 modules
|
||
|
||
clean:
|
||
$(MAKE) -C $(KDIR) M=$(MKFILE_DIR) MO=$(OUT) clean
|
||
rm -rf $(OUT)
|
||
|
||
compdb: all
|
||
$(MAKE) -C $(KDIR) M=$(MKFILE_DIR) MO=$(OUT) compile_commands.json
|
||
|
||
")
|
||
|
||
add_custom_target(${driver_name}_all
|
||
COMMAND ${CMAKE_MAKE_PROGRAM} -C "${common_path}" all
|
||
WORKING_DIRECTORY "${common_path}"
|
||
COMMENT "Build linux driver ${driver_name}"
|
||
VERBATIM
|
||
)
|
||
|
||
add_custom_target(${driver_name}_clean
|
||
COMMAND ${CMAKE_MAKE_PROGRAM} -C "${common_path}" clean
|
||
WORKING_DIRECTORY "${common_path}"
|
||
COMMENT "Clean linux driver ${driver_name}"
|
||
VERBATIM
|
||
)
|
||
|
||
add_custom_target(${driver_name}_compdb
|
||
COMMAND ${CMAKE_MAKE_PROGRAM} -C "${common_path}" compdb
|
||
WORKING_DIRECTORY "${common_path}"
|
||
COMMENT "Generate compile_commands.json for ${driver_name}"
|
||
VERBATIM
|
||
)
|
||
|
||
|
||
#要生成 compile_commands.json 来生成对应的cmake选项从而cmake有语法提示
|
||
|
||
#message("【\n${Makefile}】")
|
||
|
||
#message("Makefile安装在 ${install_prefix}")
|
||
#file(WRITE "${install_prefix}" "${Makefile}")
|
||
|
||
message("Makefile安装在公共路径下 ${common_path}")
|
||
file(WRITE "${common_path}/Makefile" "${Makefile}")
|
||
endfunction()
|
||
|
||
|
||
function(_create_linux_driver_proj driver_name)
|
||
set(_temp_list_ "${ARGN}")
|
||
_create_linux_driver_proj_ex(${driver_name} _temp_list_)
|
||
endfunction()
|
||
|
||
# 【内核驱动调试接口与使用方法入门】 https://zhuanlan.zhihu.com/p/1922942186057635216
|
||
# 【Linux内核kgdb实战:内核源码级调试工具】 https://zhuanlan.zhihu.com/p/1962870670770835660
|