jujiaqi 发表于 2015-6-24 16:35:54

不要错过!SourceInsight 快速、精确导入 Linux Kernel 源码的方法

本帖最后由 jujiaqi 于 2015-6-24 16:35 编辑

相信有很多人用 SourceInsight 查看 Linux Kernel 源码,但导入源码时会遇到一些问题。
1、如果把整个源码树都导入进去,查看符号定义的时候,会发现有大量重复定义,很难找到正确的位置
2、如果手动导入只和该硬件平台相关的源码,工作量太大
本帖提供了一个方法,可用脚本生成只和该硬件平台相关的源码的文件列表,然后通过该文件列表,将相应文件导入 SourceInsight 。
以下是步骤,共4步:
1、新建 SourceInsight 项目
   先不要导入文件,停在如下界面:
   

2、完整编译内核,将编译时输出的信息保存到一个文件中
    例如:
    make ARCH=arm > build_log.txt
    build_log.txt 文件中内容大致如下:
    CC      init/main.o
CHK   include/generated/compile.h
CC      init/do_mounts.o
HOSTCCusr/gen_init_cpio
CC      arch/arm/vfp/vfpmodule.o
CC      arch/arm/kernel/elf.o
AS      arch/arm/kernel/entry-armv.o
AS      arch/arm/vfp/entry.o
AS      arch/arm/kernel/entry-common.o
CC      arch/arm/kernel/irq.o
AS      arch/arm/vfp/vfphw.o
GEN   usr/initramfs_data.cpio
CC      arch/arm/kernel/opcodes.o

3、生成文件列表
   下载 帖子 最后面的附件,解压后是 linux shell 脚本。
    编辑脚本两个变量,ARCH 和 MACH,MACH是平台的名字。如果你用的平台对应 arch/arm/mach-at91 的话,就改成 MACH=at91,以此类推。
   
    在内核源码目录下执行:
    ./sg.sh build_log.txt file_list.txt
    这样,SourceInsight 需要的 文件列表 file_list.txt 就生成了。里面的内容大致如下:
   

4、导入文件列表
   回到 SourceInsight,点击窗口右下角 help 按钮上方的 “add from list” 按钮导入生成的 file_list.txt 文件。
   
   到此为止,文件导入完成了。重新打开工程,会提示同步、构建,之后就可以正常的查看源码了。

这样导入的文件和硬件平台是完全对应的。
下面是本帖的核心,就是这个脚本,有兴趣的可以看看:
    #!/bin/sh
ARCH=arm
MACH=at91
FILE_IN=$1
FILE_OUT=$2

# .c
SOURCE_LIST=""

# generated file list
FILE_LIST=""

# nest depth for function get_includes()
NEST_DTPTH=0

# recursive function, used to get included files from files.
# result is stored in FILE_LIST
# $1 : file list, e.g. "fs/ext4/file.c fs/ext4/fsync.c"
get_includes()
{
        local includes
        local file

        for file in $1
        do
                if [ ! -e ${file} ]; then
                        continue
                fi

                if echo "${FILE_LIST}" | grep -E ${file} > /dev/null; then
                        continue
                fi
                FILE_LIST="${FILE_LIST} ${file}"

                NEST_DTPTH=$((NEST_DTPTH+1))
                echo "<${NEST_DTPTH} : ${file}"

                includes=$(                                                                                \
                        grep -E -H '^#include' ${file} |                                \
                        sed -r \
                                -e 's@^.*<(acpi/.*)>@include/\1@'                 \
                                -e 's@^.*<(asm-generic/.*)>@include/\1@'\
                                -e 's@^.*<(config/.*)>@include/\1@'         \
                                -e 's@^.*<(crypto/.*)>@include/\1@'         \
                                -e 's@^.*<(drm/.*)>@include/\1@'                 \
                                -e 's@^.*<(generated/.*)>@include/\1@'         \
                                -e 's@^.*<(keys/.*)>@include/\1@'                 \
                                -e 's@^.*<(linux/.*)>@include/\1@'                 \
                                -e 's@^.*<(math-emu/.*)>@include/\1@'         \
                                -e 's@^.*<(media/.*)>@include/\1@'                 \
                                -e 's@^.*<(misc/.*)>@include/\1@'                 \
                                -e 's@^.*<(mtd/.*)>@include/\1@'                 \
                                -e 's@^.*<(net/.*)>@include/\1@'                 \
                                -e 's@^.*<(pcmcia/.*)>@include/\1@'         \
                                -e 's@^.*<(rdma/.*)>@include/\1@'                 \
                                -e 's@^.*<(rxrpc/.*)>@include/\1@'                 \
                                -e 's@^.*<(scsi/.*)>@include/\1@'                 \
                                -e 's@^.*<(sound/.*)>@include/\1@'                 \
                                -e 's@^.*<(target/.*)>@include/\1@'         \
                                -e 's@^.*<(trace/.*)>@include/\1@'                 \
                                -e 's@^.*<(uapi/.*)>@include/\1@'                 \
                                -e 's@^.*<(video/.*)>@include/\1@'                 \
                                -e 's@^.*<(xen/.*)>@include/\1@'                 \
                                -e "s@^.*<(asm/.*)>@arch/${ARCH}/include/\1 arch/${ARCH}/include/generated/\1@"        \
                                -e "s@^.*<(mach/.*)>@arch/${ARCH}/mach-${MACH}/include/\1@"        \
                                -e 's@(^.*/)[^/]+\.c.*\"(.*)\"@\1\2@'         \
                                -e 's@/\*.*@@'                                                         \
                                -e 's@^.*\#include.*$@@'                                \
                                -e 's@^@ @' |                                                        \
                        sort |                                                                                 \
                        uniq |                                                                                \
                        tr -d '\n' |                                                                 \
                        tr -d '\r'                                                                        \
                )

                if [ -n "${includes}" ]; then
                        get_includes "${includes}"
                fi
                echo ">${NEST_DTPTH}) : ${file}"
                NEST_DTPTH=$((NEST_DTPTH-1))
        done
}

# get *.c from kernel build log
SOURCE_LIST=$(                                                \
        grep -E '^\s*CC' ${FILE_IN} |        \
        sed -r                                                         \
                -e 's/^\s*CC\s*/ /'                        \
                -e 's/\.o/\.c/'                        |        \
        tr -d '\n' |                                         \
        tr -d '\r'                                                \
)
echo ${SOURCE_LIST}
get_includes "${SOURCE_LIST}"

FILE_LIST=$(echo "${FILE_LIST}" | sed -r -e 's/\s/\r\n/g' )

echo "${FILE_LIST}" > ${FILE_OUT}

wq_601840968 发表于 2015-6-24 16:38:18

沙发 学习学习

boyiee 发表于 2015-6-24 18:10:52

这个必须顶,以前学习内核的时候确实遇到这样的问题 只是不知道这么解决 呵,后来者可以收藏了

Xplain 发表于 2015-6-24 18:26:32

楼主好人啊,我平时都是一个文件夹一个文件夹添加的

LCH201328 发表于 2015-6-24 18:29:20

好方法,我下次试试

hkchenhao 发表于 2015-6-24 18:31:10

mark,以后留着看

DWDM 发表于 2015-6-24 18:45:51

{:lol:}很好的方法

sohappyoh 发表于 2015-6-24 19:01:16

赞!!!!!

dragonbbc 发表于 2015-6-24 19:27:34

这个方法不错

my二月兰 发表于 2015-6-24 19:50:52

真心不错,真心感谢

yuntianrenren 发表于 2015-6-24 20:11:42

太好了。。之前一直是全部加到工程里面看,太乱了。{:lol:}

linhuaou 发表于 2015-6-24 21:32:16

学习了,明天试一试。

lubing521 发表于 2015-6-24 22:25:37

此方法甚好,我以前也是一个个文件夹添加的。

小溪 发表于 2015-6-25 07:06:49

方法真不错,有空验证一下

love_zjb 发表于 2015-6-25 08:05:55

绝对赞…方法好。

bondxie3 发表于 2015-6-25 08:14:33

楼主真用心啊, 学习啦!

johnny412 发表于 2015-6-25 08:39:11

赞,楼主太给力了!

zlyny 发表于 2015-6-25 08:41:28

本帖最后由 zlyny 于 2015-6-25 09:59 编辑

用这个方法 .h 文件能导入么
------
修改:可以导入,没看全sh脚本

lxk19781221 发表于 2015-6-25 08:46:17

快速、精确导入 Linux Kernel

gnocy 发表于 2015-6-25 08:51:24

这个好东西,每次导入Linux内核都是一大推无关的平台

布心 发表于 2015-6-25 09:01:25

找时间试一试

asbzhang 发表于 2015-6-25 09:05:59

有心人,方法不错。

KunShan_a_dai 发表于 2015-6-25 09:13:04

好方法,感谢楼主,收藏了!

alan8918 发表于 2015-6-25 09:17:34

有想法,做事方法值得学习

wangcjishu 发表于 2015-6-25 09:19:12

这个必须顶,楼主解决了很多人在阅读内核代码的问题。

wangcjishu 发表于 2015-6-25 09:32:35

楼主是不是可以考虑把 ARCH 和 MACH 这两个变量作为脚步的输入参数,这样就不用手动修改脚步内容了。
例如:sg.sharm at91 build_log.txt file_list.txt

sblpp 发表于 2015-6-25 09:37:37

必须必须顶啊!非常感谢!

菜包 发表于 2015-6-25 10:01:50

赞一个,这样看linux内核就方便多了

N_EMBED 发表于 2015-6-25 10:12:06

好方法,准备学习Linux,感谢分享。

danielyuan 发表于 2015-6-25 11:19:34

好办法,参考下

ronic 发表于 2015-6-25 11:25:14

谢谢学习了

fengyunyu 发表于 2015-6-25 11:46:38

有必要看linux源码么

elecfun 发表于 2015-6-25 12:05:06

脚本真心强大

随风飘旭 发表于 2015-6-25 12:41:51

强大,赞!

hexenzhou 发表于 2015-6-25 12:51:47

楼主厉害,非常感谢。

brightchl 发表于 2015-6-25 13:36:22

非常感谢

sj1125055001 发表于 2015-6-25 13:39:45

不错                              

zuokong2006 发表于 2015-6-25 13:40:05

学习,谢谢楼主

sbk100 发表于 2015-6-25 13:50:42

学习      

gaojieqq123 发表于 2015-6-25 14:51:43

学习了,实测 添加不完全,那些相关的 .S 汇编文件没有添加.

jujiaqi 发表于 2015-6-25 15:15:31

确实没有考虑到汇编,不过默认设置下,用 SI 阅读 ARM 汇编有难度啊,不知道有没有什么好方法

ludlee 发表于 2015-6-25 15:27:36

有时间试试

bbstr 发表于 2015-6-25 15:39:51

jujiaqi 发表于 2015-6-25 15:15
确实没有考虑到汇编,不过默认设置下,用 SI 阅读 ARM 汇编有难度啊,不知道有没有什么好方法 ...

建议楼主把acpi这些头文件的搜索,改成目录递归查询的方式,就能不仅linux代码,ucos,mbed,.... 都能用了

gaojieqq123 发表于 2015-6-25 15:48:45

jujiaqi 发表于 2015-6-25 15:15
确实没有考虑到汇编,不过默认设置下,用 SI 阅读 ARM 汇编有难度啊,不知道有没有什么好方法 ...

大概看了下LZ的脚本,LZ你只解析了C语言的 CC 没有解析汇编的 AS ,能加上解析AS的么?

bbstr 发表于 2015-6-25 15:54:50

linux里的汇编就那么几个,比较好找的

jujiaqi 发表于 2015-6-25 16:40:48

bbstr 发表于 2015-6-25 15:39
建议楼主把acpi这些头文件的搜索,改成目录递归查询的方式,就能不仅linux代码,ucos,mbed,.... 都能用了 ...

acpi 这几行可不是搜索头文件,而是做替换,比如,将头文件包含指示“#include <linux/module.h>” 替换成 文件路径"include/linux/module"。
这个方法并不是将 include 下面所有的头文件都包含进来,而是从参与编译的C文件出发,递归搜索引用的头文件,避免包含无用的头文件。

bbstr 发表于 2015-6-25 16:49:09

了解了,那如果需要用到的头文件不是在linux/,而是在别的某个路径下的,是-e 's@^.*<(path_to_inc_dir/.*)>@include/\1@'         \                  
?

jujiaqi 发表于 2015-6-25 16:58:55

bbstr 发表于 2015-6-25 16:49
了解了,那如果需要用到的头文件不是在linux/,而是在别的某个路径下的,是-e 's@^.*@include/\1@'         \ ...

凡是引用 include 目录下头文件的地方,都要做替换,因为编译内核时, include 目录是被加入到系统搜索路径的,所以可以使用
    #include <linux/xxx.h>
    #include <sound/xxx.h>
    #include <video/xxx.h>
liniux sound video 都是 include 目录下的子目录。
所以说,这一句只适合处理包含 include 目录下头文件的情况

jujiaqi 发表于 2015-6-25 17:02:18

gaojieqq123 发表于 2015-6-25 15:48
大概看了下LZ的脚本,LZ你只解析了C语言的 CC 没有解析汇编的 AS ,能加上解析AS的么? ...

# get *.c from kernel build log
SOURCE_LIST=$(                                                \
        grep -E '^\s*CC' ${FILE_IN} |        \
        sed -r                                                         \
                -e 's/^\s*CC\s*/ /'                        \
                -e 's/\.o/\.c/'                        |        \
        tr -d '\n' |                                         \
        tr -d '\r'                                                \
)
ASSEMBLY_LIST=$(                                                \
        grep -E '^\s*AS' ${FILE_IN} |        \
        sed -r                                                         \
                -e 's/^\s*AS\s*/ /'                        \
                -e 's/\.o/\.S/'                        |        \
        tr -d '\n' |                                         \
        tr -d '\r'                                                \
)
SOURCE_LIST="${SOURCE_LIST}${ASSEMBLY_LIST}"

要添加汇编,可以这样做。对比原来的脚本,就知道改哪里了。
因为不太了解汇编文件的一些包含规则,所以这样做是否准确还不能确定。

jujiaqi 发表于 2015-6-25 17:07:27

wangcjishu 发表于 2015-6-25 09:32
楼主是不是可以考虑把 ARCH 和 MACH 这两个变量作为脚步的输入参数,这样就不用手动修改脚步内容了。
例如 ...

好建议,就是找不到编辑帖子的入口了{:sweat:} 。难道现在发布的帖子不让编辑了吗?

hxke 发表于 2015-6-25 17:10:34

可以导RT-Thread么?

bbstr 发表于 2015-6-25 17:19:51

导u-boot,rt-thread,ucos,mbed,。。。。

gaojieqq123 发表于 2015-6-25 17:32:54

jujiaqi 发表于 2015-6-25 17:07
好建议,就是找不到编辑帖子的入口了 。难道现在发布的帖子不让编辑了吗? ...

COOL !完美了 !汇编也加入了.

dahai168 发表于 2015-6-25 17:33:53

好方法,下次再用。{:handshake:}

jujiaqi 发表于 2015-6-25 17:42:28

bbstr 发表于 2015-6-25 17:19
导u-boot,rt-thread,ucos,mbed,。。。。

需要大家自由发挥了,这个脚本提供了一个框架。
如果目标换成 uboot、rtt等,难点在于:
需要清楚其源码结构,才能处理一些像"#include <linux/xxx.h>"这样的路径不完全的头文件包含指令。

bbstr 发表于 2015-6-25 17:54:35

jujiaqi 发表于 2015-6-25 17:42
需要大家自由发挥了,这个脚本提供了一个框架。
如果目标换成 uboot、rtt等,难点在于:
需要清楚其源码 ...

{:lol:}这个还是比较清楚的,就是你这个shell脚本一时不好懂

bbstr 发表于 2015-6-25 17:55:58

不知道这个思路行不行,将一个工程里的所有头文件做成一个链表,解析c时去链表里查,然后将路径摘出来作为list

farmerzhangdl 发表于 2015-6-25 19:22:48

这个真是不错

lans0625 发表于 2015-6-25 19:56:17

这个方法太神奇了。

fengyuxiaoxiao 发表于 2015-6-25 20:15:44

一直使用这个

lgnq 发表于 2015-6-25 20:28:03

very good

lize91 发表于 2015-6-25 20:31:33

这个办法好,顶起~~

lize91 发表于 2015-6-25 21:08:45

奇怪了 为什么我执行脚本 输出的的东西都在屏幕上 而没有写进参数2的txt文件{:sad:}

wangcjishu 发表于 2015-6-25 21:20:28

jujiaqi 发表于 2015-6-25 17:07
好建议,就是找不到编辑帖子的入口了 。难道现在发布的帖子不让编辑了吗? ...

我看了一下我之前发的帖子也没找到编辑,楼主的脚本写的挺好,感觉递归能把挺复杂的问题给简化了。
此外问个问题sed 中's@^.*<(acpi/.*)>@include/\1@' 中\1是指被替换的那个参数(即^.*<(acpi/.*)>)是吧,这个是sed的内部变量吗?

dmzy 发表于 2015-6-25 21:21:25

MARK                           

xwkm 发表于 2015-6-26 06:07:24

不一定用sed啊。cut命令也可以

huangzzjy22 发表于 2015-6-26 06:52:45

先收藏,谢谢

jielove2003 发表于 2015-6-26 07:26:53

这个脚本能否用于uboot?

tarchen 发表于 2015-6-26 07:28:20

太好了,谢谢分享!

yuzr 发表于 2015-6-26 10:01:28

谢谢楼主的经验分享。

Honey_comb 发表于 2015-6-26 10:06:00

kernel mark

jujiaqi 发表于 2015-6-26 12:51:18

lize91 发表于 2015-6-25 21:08
奇怪了 为什么我执行脚本 输出的的东西都在屏幕上 而没有写进参数2的txt文件 ...

屏幕上显示的是当前处理的文件。脚本运行结束后,才会创建文件,写入文件列表。

Hassen_JYA 发表于 2015-6-26 13:02:29

教程写得清晰明白,感谢lz,收藏了先。

ztg328 发表于 2015-6-26 16:05:25

收藏,好东西

liucoldstarplus 发表于 2015-6-27 01:14:00

这个主意不错,值得赞一下。

nfchg 发表于 2015-6-27 05:54:30

好东西,Mark

sgweilong 发表于 2015-6-27 09:54:50

不得不顶,mark之

ljmdzyx 发表于 2015-6-27 23:34:40

必须顶起,省去很多时间啊。

showcan 发表于 2015-7-3 10:20:29

是个好方法,学习了!!

ggchao 发表于 2015-7-3 10:53:02

niub的帖子 实践下

fhqiplj 发表于 2015-7-3 11:10:58

收藏了,非常感谢。
是不是对于bootload等类似的工程也可以这样导入?

licheng0620 发表于 2015-7-3 14:28:50

想知道国外的linux开发人员一般是怎么搞的

DboyLQ 发表于 2015-7-3 16:21:19

Mark,Source Insight 通过编译文件列表导入Linux代码。谢谢lz分享!

timi 发表于 2015-7-3 16:23:10

好帖呀~~~~~~~~~~~~~~

QQ373466062 发表于 2015-7-7 10:29:15

本帖最后由 QQ373466062 于 2015-7-7 10:32 编辑

我也写了一个类似的脚本,不过应该比楼主的这个包含的更全。欢迎拍砖。 一起改进。
http://www.amobbs.com/thread-5626800-1-1.html

jujiaqi 发表于 2015-7-10 16:33:34

QQ373466062 发表于 2015-7-7 10:29
我也写了一个类似的脚本,不过应该比楼主的这个包含的更全。欢迎拍砖。 一起改进。
http://www.amobbs.com/ ...

你那个做的挺全面的,而且脚本写得真漂亮

广轻电气091 发表于 2015-10-13 14:55:47

谢谢楼主分享

贪狼lyb 发表于 2015-10-13 16:01:15

赞一下,现在天天用这玩意

blackcafe 发表于 2015-10-13 19:44:07

赞一个,感谢楼主分享

DboyLQ 发表于 2015-10-20 10:47:05

Mark,SourceInsight添加linux内核源代码,谢谢lz分享。

dwiller_ARM 发表于 2015-10-20 10:59:01

好东西,值得看下!!

k_ewell 发表于 2015-10-21 14:14:04

谢谢分享!

jungleyang 发表于 2015-10-21 14:44:13

好东西,以前看的老师加入些垃圾文件,{:biggrin:}

sys_suweixiao 发表于 2015-10-21 16:48:05

好久不用mark!

iridescent_rsy 发表于 2015-10-21 19:14:17

收藏,正在学呢~~~

edkaifa 发表于 2015-12-11 00:50:33

回头试试

sender 发表于 2015-12-11 09:04:33

高手,去试试。

haphard 发表于 2015-12-11 11:45:52

挺好的,谢了

远去的记忆 发表于 2015-12-11 13:00:00

好东东{:smile:}

sandman 发表于 2015-12-11 13:06:52

感谢分享,导入确实方便
页: [1] 2
查看完整版本: 不要错过!SourceInsight 快速、精确导入 Linux Kernel 源码的方法