lldb常用命令与调试技巧
LLDB
是个开源的内置于XCode
的调试工具,它能帮助我们在开发中更快的定位和调试bug
,无论正向和逆向开发中都有很大的作用。lldb对于命令的简称,是头部匹配方式,只要不混淆(不提示歧义),你可以随意简称某个命令。
下面是xcode debug区域的按钮讲解
Xcode调试区按钮讲解二、调试技巧单步调试单步调试通常分为两大类,一类为源码级别(source level)
,一类为指令级别(instrution level)
。一行源代码一般需要多行汇编才可以实现,所以当我们越狱开发调试汇编指令单步调试需要用到(instrution level)指令级别。而每一大类又分为step-in和step-over,step-in会进入函数调用,而step-over会跳过函数调用。
(lldb) thread step-in(lldb) step(lldb) s
以上三条命令是等同的,在有函数调用的位置,会
进入函数内部。
(lldb) thread step-over(lldb) next(lldb) n
以上三条命令是等同的,在有函数调用的位置,不会
进入函数内部。
2)指令级别(instruction level)总结
s和n都是跳转到断点的下一行代码位置,区别为,如果下一行代码有函数调用,s会进入函数内部,n则会跳过函数执行。如果没有函数调用则两组命令没有任何区别。
指令级别的调试,我们需要在xcode的选项卡中设置Debug->Debug Workflow->Always Show Disassembly
,这时候才能看到效果。指令级别的lldb对应的正好是我们点击按钮的同时按下了ctrl键。
(lldb) thread step-inst(lldb) si
以上两条命令是等同的,在汇编界面,跳转下一步,在有bl
指令的地方,si``会
单步进入到bl
指令所跳转的子函数内部
(lldb) thread step-inst-over(lldb) ni
以上两条命令是等同的,在汇编界面,跳转下一步,在有bl
指令的地方,ni``不会
单步进入到bl
指令所跳转的子函数内部
(lldb) thread step-out(lldb) finish(lldb) f
c
是continue
的简写 表示继续运行s(si)、n(ni)和Xcode调试工具的对应关系如文开始的图三、lldb常用命令1.计算表达式命令(expression、po、p)expression
可简写为expr
计算以及生成一个表达式(lldb) expr (int)printf ("Print nine: %d.\n", 4 + 5) Print nine: 9.(int) $0=15
创建一个变量并分配值(lldb) expr int $val=10(lldb) expr $val(int) $val=10
exp
打印值、修改值(lldb) expr width(CGFloat) $0=10(lldb) expr width=2(CGFloat) $1=2(lldb) po width4(lldb) p width(CGFloat) $3=2
p
、po
与expr
的关系(lldb) expr -- person(Person *) $0=0x000000010053b7f0(lldb) p person(Person *) $1=0x000000010053b7f0(lldb) expr -o -- person<Person: 0x10053b7f0>(lldb) po person<Person: 0x10053b7f0>
使用p做进制转换总结
p
是expr --
的简写,它的工作是把接收到参数在当前环境中进行编译,然后打印出来po
是expr -o --
的简写,它所做的操作和p相同。如果接收到的参数是一个指针,那么它会调用对象的description
方法并打印;如果接收到的参数是一个core foundation
对象,那么它会调用CFShow
方法并打印。如果这两个方法都调用失败,那么po
打印出和p
相同的内容。
//默认打印为10进制(lldb) p 10(int) $0=10//转16进制(lldb) p/x 10(int) $1=0x0000000a//转8进制(lldb) p/o 10(int) $2=012//转二进制(lldb) p/t 10(int) $3=0b00000000000000000000000000001010//字符转10进制数字(lldb) p/d 'A'(char) $4=65//10进制数字转字符(lldb) p/c 66(int) $5=B\0\0\0
2. 内存读取(lldb) x person0x10053a6b0: 5d 22 00 00 01 80 1d 00 00 00 00 00 00 00 00 00 ]"..............0x10053a6c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................(lldb) x/4gx person0x10053a6b0: 0x001d80010000225d 0x00000000000000000x10053a6c0: 0x0000000000000000 0x0000000000000000(lldb) x/3wx person0x10053a6b0: 0x0000225d 0x001d8001 0x00000000(lldb) x &width0x7ffeefbff4f0: 00 00 00 00 00 00 00 00 b0 a6 53 00 01 00 00 00 ..........S.....0x7ffeefbff500: 30 f5 bf ef fe 7f 00 00 01 00 00 00 00 00 00 00 0...............(lldb) x/4gx &width0x7ffeefbff4f0: 0x0000000000000000 0x000000010053a6b00x7ffeefbff500: 0x00007ffeefbff530 0x0000000000000001(lldb) x/4go0x7ffeefbff510: 037777357577724400x7ffeefbff518: 037777553217763110x7ffeefbff520: 000x7ffeefbff528: 01
x
是读取内存的命令,x/4gx
中第一个x
是读取内存命令,后面的g
是每次读取8字节
,x
的意思是16进制显示结果
,4
表示连续打印4段
。
g
,常用的大小格式为b
对应byte 1字节
,h
对应half word 2字节
,w
对应word 4字节
,g
对应giant word 8字节
对于x
,我们还可以用o
对应8机制
,b
对应2进制
,x
对应16进制
,f
对应浮点
,d
对应10进制
3.call
方法调用(lldb) call width(CGFloat) $0=0(lldb) call testFunction()123456
4.变量检查(frame)(lldb) fr v b(Int??) b=nil(lldb) fr v -r b(Int??) b=nil(lldb) fr v -R b(Swift.Optional<Swift.Optional<Swift.Int>>) b=some { some=none { some={ _value=0 } }}(lldb) fr v -a b(Int??) b=nil
我们常用fr v -R
来查看类型的结构
bt
命令)bt
是thread backtrace
的简写,如果嫌堆栈打印太长,可以加一个限制,如bt 10
,只打印10行
(lldb) thread backtrace 1* thread #1, queue='com.apple.main-thread', stop reason=step over * frame #0: 0x0000000100000e02 TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:30:5 frame #1: 0x00007fff6b47fcc9 libdyld.dylib`start + 1(lldb) thread backtrace -c 1* thread #1, queue='com.apple.main-thread', stop reason=step over frame #0: 0x0000000100000e02 TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:30:5(lldb) bt 10* thread #1, queue='com.apple.main-thread', stop reason=breakpoint 1.1 * frame #0: 0x0000000100000df1 TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:28:13 frame #1: 0x00007fff6b47fcc9 libdyld.dylib`start + 1
我们的案例一共只有3行,没达到触发10行限制的条件。
2)thread list
列出当前线程列表(lldb) thread listProcess 4500 stopped* thread #1: tid=0x33d9a, 0x0000000100000e02 TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:30:5, queue='com.apple.main-thread', stop reason=step over
3)thread select
选取某个线程作为后续命令的默认线程(lldb) thread select 1
4)frame select
根据下标选择堆栈列表中某帧(lldb) bt* thread #1, queue='com.apple.main-thread', stop reason=breakpoint 1.1 * frame #0: 0x0000000100000deb TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:37:5 frame #1: 0x00007fff6ce68cc9 libdyld.dylib`start + 1(lldb) frame select 1frame #1: 0x00007fff6ce68cc9 libdyld.dylib`start + 1libdyld.dylib`start:-> 0x7fff6ce68cc9 <+1>: movl %eax, %edi 0x7fff6ce68ccb <+3>: callq 0x7fff6ce7c82e ; symbol stub for: exit 0x7fff6ce68cd0 <+8>: hlt 0x7fff6ce68cd1 <+9>: nop
此时会跳转到汇编页面,即使没有设置Always Show Disassembly
frame info
显示当前帧信息(lldb) bt* thread #1, queue='com.apple.main-thread', stop reason=breakpoint 1.1 * frame #0: 0x0000000100000deb TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:37:5 frame #1: 0x00007fff6ce68cc9 libdyld.dylib`start + 1(lldb) frame infoframe #0: 0x0000000100000deb TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:37:5(lldb) frame select 1frame #1: 0x00007fff6ce68cc9 libdyld.dylib`start + 1libdyld.dylib`start:-> 0x7fff6ce68cc9 <+1>: movl %eax, %edi 0x7fff6ce68ccb <+3>: callq 0x7fff6ce7c82e ; symbol stub for: exit 0x7fff6ce68cd0 <+8>: hlt 0x7fff6ce68cd1 <+9>: nop (lldb) frame infoframe #1: 0x00007fff6ce68cc9 libdyld.dylib`start + 1
6)up
移动当前帧(序号加1) down
移动当前帧(序号减1)(lldb) bt* thread #1, queue='com.apple.main-thread', stop reason=breakpoint 1.1 * frame #0: 0x0000000100000ddf TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:36:5 frame #1: 0x00007fff6ce68cc9 libdyld.dylib`start + 1(lldb) upframe #1: 0x00007fff6ce68cc9 libdyld.dylib`start + 1libdyld.dylib`start:-> 0x7fff6ce68cc9 <+1>: movl %eax, %edi 0x7fff6ce68ccb <+3>: callq 0x7fff6ce7c82e ; symbol stub for: exit 0x7fff6ce68cd0 <+8>: hlt 0x7fff6ce68cd1 <+9>: nop (lldb) uperror: Already at the top of the stack.(lldb) downframe #0: 0x0000000100000ddf TestWeak`main(argc=1, argv=0x00007ffeefbff530) at main.m:36:5 33 person.age=5; 34 35 CGFloat width=10;-> 36 testFunction(); ^ 37 NSLog(@"hello"); 38 return 0; 39 }(lldb) downerror: Already at the bottom of the stack.
可以看到,如果已经是栈顶或者栈底,会提示已在最顶或者最底部。
7)register read
读取寄存器 register write
写入寄存器(lldb) register write rax 123(lldb) register read rax rax=0x000000000000007b(lldb) register write rax 1(lldb) register read rax rax=0x0000000000000001
8)thread return
跳出当前方法的执行Debug的时候,也许会因为各种原因,我们不想让代码执行某个方法,或者要直接返回一个想要的值。这时候就该thread return上场了。有返回值的方法里,如:numberOfSectionsInTableView:,直接thread return 20,就可以直接跳过方法执行,返回20.
//跳出方法(lldb) thread return//让带有返回int值的方法直接跳出,并返回值20(lldb) thread return 20
6.镜像(image)操作1) image list
镜像列表(lldb) image list[ 0] 9D17C7F5-7D6B-387D-81E5-1C7ED33709BE 0x0000000100000000 /Users/liu_david/Library/Developer/Xcode/DerivedData/TestWeak-egnzdbndwsiikvcheqmcxvkqnwbw/Build/Products/Debug/TestWeak [ 1] F9D4DEDC-8296-3E3F-B517-9C8B89A4C094 0x0000000100009000 /usr/lib/dyld [ 2] 7C69F845-F651-3193-8262-5938010EC67D 0x00007fff35437000 /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation [ 3] 6DF81160-5E7F-3E31-AA1E-C875E3B98AF6 0x00007fff6bcad000 /usr/lib/libobjc.A.dylib [ 4] C0C9872A-E730-37EA-954A-3CE087C15535 0x00007fff69e4d000 /usr/lib/libSystem.B.dylib [ 5] C0D70026-EDBE-3CBD-B317-367CF4F1C92F 0x00007fff32d7a000 /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation [ 6] B6124448-7690-34AE-8939-ED84AAC630CE 0x00007fff6a04f000 /usr/lib/libauto.dylib
这里只截取了部分,因为所有的镜像有几百个,包括了各种动态库
2)image lookup -a
查看崩溃位置2020-09-16 00:41:45.605355+0800 TestWeak[2106:87796] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndexedSubscript:]: index 4 beyond bounds [0 .. 2]'*** First throw call stack:( 0 CoreFoundation 0x00007fff32e79b57 __exceptionPreprocess + 250 1 libobjc.A.dylib 0x00007fff6bcc05bf objc_exception_throw + 48 2 CoreFoundation 0x00007fff32f2859e -[__NSCFString characterAtIndex:].cold.1 + 0 3 CoreFoundation 0x00007fff32deab70 +[NSNull null] + 0 4 TestWeak 0x0000000100001b8f -[Person getInt] + 287 5 TestWeak 0x0000000100001d73 main + 99 6 libdyld.dylib 0x00007fff6ce68cc9 start + 1 7 ??? 0x0000000000000001 0x0 + 1)libc++abi.dylib: terminating with uncaught exception of type NSException(lldb) image lookup --address 0x0000000100001b8f Address: TestWeak[0x0000000100001b8f] (TestWeak.__TEXT.__text + 335) Summary: TestWeak`-[Person getInt] + 287 at main.m:31:13(lldb) image lookup -a 0x0000000100001b8f Address: TestWeak[0x0000000100001b8f] (TestWeak.__TEXT.__text + 335) Summary: TestWeak`-[Person getInt] + 287 at main.m:31:13
如上所示,我们先得到开始一部分数组越界的崩溃信息,我们找到stack
中4
的位置,可以看到是调用了[person getInt]
,这时候我们使用image lookup -a 地址
就可以找到崩溃位置。image lookup -a
是image lookup --address
的简写
image lookup -v -a
查找完整的源代码行信息同样使用上方数组越界案例
(lldb) image lookup -v -a 0x0000000100001b8f Address: TestWeak[0x0000000100001b8f] (TestWeak.__TEXT.__text + 335) Summary: TestWeak`-[Person getInt] + 287 at main.m:31:13 Module: file="/Users/liu_david/Library/Developer/Xcode/DerivedData/TestWeak-egnzdbndwsiikvcheqmcxvkqnwbw/Build/Products/Debug/TestWeak", arch="x86_64" CompileUnit: id={0x00000000}, file="/Users/liu_david/Desktop/TestWeak/TestWeak/main.m", language="objective-c" Function: id={0x100000162}, name="-[Person getInt]", range=[0x0000000100001a70-0x0000000100001bef) FuncType: id={0x100000162}, byte-size=0, decl=main.m:29, compiler_type="int (void)" Blocks: id={0x100000162}, range=[0x100001a70-0x100001bef) LineEntry: [0x0000000100001b76-0x0000000100001b97): /Users/liu_david/Desktop/TestWeak/TestWeak/main.m:31:13 Symbol: id={0x0000001c}, range=[0x0000000100001a70-0x0000000100001bf0), name="-[Person getInt]" Variable: id={0x10000017f}, name="self", type="Person *const", location=DW_OP_fbreg(-40), decl=Variable: id={0x10000018b}, name="_cmd", type="SEL", location=DW_OP_fbreg(-48), decl=Variable: id={0x100000197}, name="array", type="NSArray *", location=DW_OP_fbreg(-56), decl=main.m:30
从信息可以看到,我们有三个变量入栈,分别是self
、_cmd
、array
image lookup -v -a
是image lookup -v --address
的简写
image lookup -name
查找方法来源(lldb) image lookup getInterror: invalid combination of options for the given command(lldb) image lookup -name getInt1 match found in /Users/liu_david/Library/Developer/Xcode/DerivedData/TestWeak-egnzdbndwsiikvcheqmcxvkqnwbw/Build/Products/Debug/TestWeak: Address: TestWeak[0x0000000100001a70] (TestWeak.__TEXT.__text + 48) Summary: TestWeak`-[Person getInt] at main.m:291 match found in /usr/lib/libicucore.A.dylib: Address: libicucore.A.dylib[0x000000000003b046] (libicucore.A.dylib.__TEXT.__text + 239078) Summary: libicucore.A.dylib`icu::ResourceBundle::getInt(UErrorCode&) const1 match found in /System/Library/Frameworks/Security.framework/Versions/A/Security: Address: Security[0x000000000012260e] (Security.__TEXT.__text + 1184206) Summary: Security`Security::Context::getInt(unsigned int, int) const1 match found in /System/Library/Frameworks/SceneKit.framework/Versions/A/SceneKit: Address: SceneKit[0x000000000024f396] (SceneKit.__TEXT.__text + 2414070) Summary: SceneKit`getInt(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, int&, bool, bool)1 match found in /usr/lib/libTelephonyUtilDynamic.dylib: Address: libTelephonyUtilDynamic.dylib[0x0000000000012e10] (libTelephonyUtilDynamic.dylib.__TEXT.__text + 69904) Summary: libTelephonyUtilDynamic.dylib`ctu::cf::map_adapter::getInt(__CFString const*, int) const1 match found in /System/Library/PrivateFrameworks/CorePrediction.framework/Versions/A/CorePrediction: Address: CorePrediction[0x00000000000475c4] (CorePrediction.__TEXT.__text + 286980) Summary: CorePrediction`-[CPMLEvalutionResult getInt]
可以看到,所有match到的方法位置信息都给我们了。只不过只有我们自定义的方法给了我们是在main.m:29
image lookup -type
查看成员(lldb) image lookup -type PersonBest match found in /Users/liu_david/Library/Developer/Xcode/DerivedData/TestWeak-egnzdbndwsiikvcheqmcxvkqnwbw/Build/Products/Debug/TestWeak:id={0x10000002b}, name="Person", byte-size=24, decl=main.m:12, compiler_type="@interface Person : NSObject{ BOOL _isMan; short _age; NSString * _name;}@property(nonatomic, copy, readwrite, getter=name, setter=setName:) NSString *name;@property(nonatomic, assign, readwrite, getter=age, setter=setAge:) short age;@property(nonatomic, assign, readwrite, getter=isMan, setter=setIsMan:) BOOL isMan;@end"(lldb) image lookup -type NSObjectBest match found in /Users/liu_david/Library/Developer/Xcode/DerivedData/TestWeak-egnzdbndwsiikvcheqmcxvkqnwbw/Build/Products/Debug/TestWeak:id={0x7fffffff000002e8}, name="NSObject", byte-size=8, decl=NSObject.h:53, compiler_type="@interface NSObject{ Class isa;}@end"(lldb) im loo -t PersonBest match found in /Users/liu_david/Library/Developer/Xcode/DerivedData/TestWeak-egnzdbndwsiikvcheqmcxvkqnwbw/Build/Products/Debug/TestWeak:id={0x10000002b}, name="Person", byte-size=24, decl=main.m:12, compiler_type="@interface Person : NSObject{ BOOL _isMan; short _age; NSString * _name;}@property(nonatomic, copy, readwrite, getter=name, setter=setName:) NSString *name;@property(nonatomic, assign, readwrite, getter=age, setter=setAge:) short age;@property(nonatomic, assign, readwrite, getter=isMan, setter=setIsMan:) BOOL isMan;@end"
可以看到,image lookup -type
可以用im loo -t
简写
b
在某个函数设置一个断点(lldb) b getIntBreakpoint 2: 6 locations.(lldb) cProcess 2274 resuming
如代码所示,我们使用b
在getInt
方法中设置了一个断点,执行c
指令继续运行后,代码会断在getInt
方法中第一行b
是以下的简写
br s -n
breakpoint set --name
2) b+文件:行
在某个文件的某行设置一个断点(lldb) b main.m:45Breakpoint 2: where=TestWeak`main + 102 at main.m:45:5, address=0x0000000100001d76(lldb) cProcess 2297 resuming
这种写法是以下命令的简写:
br s -f main.m -l 45
breakpoint set --file main.m --line 45
3) b -[类名 方法名]
、b +[类名 方法名]
设置类中方法的断点b -[类名 方法名]
是设置实例方法的断点b +[类名 方法名]
是设置类方法的断点(lldb) b -[Person getInt]Breakpoint 2: where=TestWeak`-[Person getInt] + 30 at main.m:30:24, address=0x0000000100001a6e(lldb) b +[Person aaa]Breakpoint 3: where=TestWeak`+[Person aaa] + 23 at main.m:27:5, address=0x0000000100001a37(lldb) cProcess 2344 resuming(lldb) cProcess 2344 resuming
这种写法是以下命令的简写:
breakpoint set -- name -[类名 方法名]
4) breakpoint list
查看断点列表(lldb) breakpoint listCurrent breakpoints:1: file='/Users/liu_david/Desktop/TestWeak/TestWeak/main.m', line=39, exact_match=0, locations=1, resolved=1, hit count=1 1.1: where=TestWeak`main + 41 at main.m:39:5, address=0x0000000100001d19, resolved, hit count=1 2: file='/Users/liu_david/Desktop/TestWeak/TestWeak/main.m', line=30, exact_match=0, locations=1, resolved=1, hit count=0 2.1: where=TestWeak`-[Person getInt] + 30 at main.m:30:24, address=0x0000000100001a6e, resolved, hit count=0 3: file='/Users/liu_david/Desktop/TestWeak/TestWeak/main.m', line=27, exact_match=0, locations=1, resolved=1, hit count=0 3.1: where=TestWeak`+[Person aaa] + 23 at main.m:27:5, address=0x0000000100001a37, resolved, hit count=0
5) br en 序号
、br dis 序号
启用/禁用断点(lldb) br dis 21 breakpoints disabled.(lldb) br en 21 breakpoints enabled.
在使用br dis 2
后,2号断点就会变灰不可用,br en 2
后,2号断点又会恢复亮色可使用状态
br en 序号
是breakpoint enable 序号
的简写br dis 序号
是breakpoint disable 序号
的简写6) br del 序号
根据序号移除一个断点(lldb) br del 21 breakpoints deleted; 0 breakpoint locations disabled.
在删除2号断点后,它将立刻在界面上移除。
br del 序号
是breakpoint delete 序号
的简写
Xcode中的断点调试技巧可参考:iOS Xcode Breakpoint(断点)调试
参考链接:
GDB to LLDB command mapiOS之LLDB常用命令我们在安装完成后,就要开始 CLion 的使用,首先在具体操作之前先解答大家最关心的几个问题。
点击获CLion官方正式版
CLion 是跨平台的 IDE 吗?
是的,您可以在 Windows、macOS 和 Linux 上安装和运行 CLion。
有关特定于操作系统的说明,请阅读安装要求。
有关如何为您的操作系统选择正确的键盘映射的说明,请参阅CLion 键盘快捷键,并了解最有用的快捷键。
可以使用哪些编译器和调试器?
CLion 支持在所有平台上使用GDB(捆绑或自定义)以及在 macOS 和 Linux 上使用捆绑的LLDB进行调试。此外,Windows 上的 MSVC 工具链还有一个基于 LLDB 的调试器。有关详细信息,请参阅下面的调试部分和调试器选项页面。
支持哪些构建系统?项目格式有哪些?
CLion 与CMake构建系统完全集成:您可以无缝地创建、打开、构建和运行/调试CMake 项目。CMake 本身捆绑在 CLion 中,因此您不需要单独安装它,除非您决定使用自定义版本。
除了 CMake,CLion 还支持Makefile、编译数据库和Gradle项目,目前不支持在 CLion 重新创建这些类型的新项目。
需要提前安装任何东西吗?
Windows
在 Windows 上,CLion 需要一个工作环境。CLion 捆绑了 MinGW 工具集的一个版本以进行快速设置。您可以使用这个捆绑的工具链或切换到另一个 MinGW 安装、Cygwin 或 Microsoft Visual C++。如果您正在使用 WSL 或 Docker,则还需要安装它们。详情请参阅后续的Windows的配置教程。
macOS
在 macOS 上,可能已经安装了所需的工具。如果没有,请按照在 macOS 上配置 CLion中所述更新命令行开发人员工具。
Linux
在 Linux 上,也可能预先安装了编译器和make 。否则,在 Debian/Ubuntu 的情况下,安装build_essentials包,如果需要,安装llvm包以获取 Clang。
是否也支持其他 C++ 语言?
是的,CLion 完全支持Python、Objective-C/C++、HTML(包括 HTML5)、CSS、JavaScript 和 XML。对这些语言的支持是通过默认启用的捆绑插件实现的。有关更多详细信息,请参阅后续关于不同语言的 CLion 功能文章。
您可以安装其他插件以获得 CLion 支持的更多语言(例如Rust、Swift或Markdown)。
打开/创建一个项目
打开本地项目
对于CMake项目,请使用以下选项之一:
选择文件 | 打开并找到项目目录。这个目录应该包含一个CMakeLists.txt文件。选择文件 | 打开并将 CLion 指向顶级CMakeLists.txt文件,然后选择Open as Project。选择文件 | 打开并找到CMakeCache.txt文件,然后选择Open as Project。要打开编译数据库项目,请转到文件 | 打开,将 CLion 指向包含compile_commands.json的文件夹或compile_commands.json文件本身(然后选择Open as Project)。
要打开Makefile项目,请转到File | 打开,将 CLion 指向包含顶级Makefile的文件夹或Makefile本身(然后选择Open as Project)。
要打开Gradle项目,请转到文件 | 打开,将 CLion 指向包含build.gradle的文件夹或build.gradle文件本身(然后选择Open as Project)。
从存储库中签出
在欢迎屏幕上单击从版本控制中签出或选择VCS | 从主菜单中从版本控制中迁出并选择您的版本控制系统。
输入凭据以访问存储并提供路径。CLion 会将存储库克隆到一个新的 CMake 项目。
创建一个新的 CMake 项目
选择文件 | 从主菜单新建项目或单击欢迎屏幕上的新建项目。
设置项目的类型:C 或 C++、可执行文件或库,请注意,STM32CubeMX和CUDA也是基于 CMake 的项目类型。
提供文件夹位置并选择语言标准。CLion 创建一个新的 CMake 项目并填写顶级CMakeLists.txt:
初始CMakeLists.txt文件已包含多个命令。在我们的教程中找到他们的描述和使用 CMake 的更多信息。
环顾四周
1.项目视图显示您的项目文件和目录。从这里,您可以管理项目文件夹(将它们标记为源、库或排除项)、添加新文件、重新加载项目以及调用其他操作,例如重新编译。
2.编辑器是您查看、编写和编辑代码的地方。编辑器在单独的选项卡中显示每个文件。您还可以垂直图标操作垂直拆分或水平拆分编辑器图标操作水平拆分以同时查看多个选项卡。
3.导航栏帮助您在文件的选项卡之间切换,工具栏提供对运行/调试和 VSC 相关操作的快速访问。
4.左侧装订线 - 编辑器左侧的垂直条纹 - 显示断点和可单击的图标,以帮助您浏览代码结构(例如,跳转到定义或声明)并运行 main()或测试。
5.右侧装订线显示代码分析结果,整体文件状态指示器位于顶部。
6.工具窗口代表特定的工具或任务,例如TODO、CMake、终端或文件结构。
7.状态栏显示项目和整个 IDE 的各种指标:文件编码、行分隔符、内存使用情况等。此外,您可以在此处找到解析上下文切换器。
每当您需要查找 IDE 操作时,请按Ctrl+Shift+A或转到帮助 | 查找 Action并开始输入您要查找的命令、设置甚至 UI 元素的名称:
自定义您的环境
更改IDE外观
在 CLion的配色方案、代码样式、键盘映射、查看模式和外观(UI 主题)之间切换的最快方法是Switch...弹出窗口。要调用它,请单击查看 | 快速切换方案或按Ctrl+`:。
要探索所有可自定义的选项,请转到Settings / PreferencesCtrl+Alt+S中的专用页面。
调整编辑器
Settings / Preferences对话框的Editor节点下的页面可帮助您调整编辑器的行为,从最常规的设置(如 Drag'n'Drop 启用和滚动配置)到突出显示颜色和代码样式选项。
代码样式可在编辑器 |下的页面中分别为每种语言配置。代码样式节点。对于C/C++,您可以设置一种预定义的代码样式或提供您自己的代码样式,并配置所需的命名约定,包括标头保护模板:
调整键盘映射
在 CLion 中,IDE 中几乎所有可能的操作都映射到键盘快捷键。要查看默认映射,请调用帮助 | 键盘快捷键 PDF 。
您可以在设置/首选项中自定义快捷方式| 键盘映射。使用预定义的键盘映射之一(Visual Studio、Emacs、Eclipse、NetBeans、Xcode 等)并根据需要对其进行调整,或者从头开始创建您自己的键盘映射。
还有一些插件可以扩展可用键盘映射列表。例如,VS Code Keymap或Vim 仿真(包括 Vim 键盘映射)。在Valuable non-bundled plugins中找到更多有用的 CLion 编辑器插件。
以上就是CLion入门指南第一部分的的相关介绍,更多关于CLion教程的内容可进入官网查看。
正值“315”消费者权益日,慧都为正版护航,联合Jetbrains厂商推出满减优惠,旗下产品最高减1200,欢迎大家进入活动详情页了解详情。
CLion| 下载试用
CLion是一款专为开发C及C++所设计的跨平台IDE。它是以IntelliJ为基础设计的,包含了许多智能功能来提高开发人员的生产力。
上一篇:N73游戏
发表评论