Cソースコードを Clang と  vscode for mac で デバッグ

# Cソースコードを Clang と vscode for mac で デバッグ

repos: https://github.com/sato1043/try_clang_env

## 概要
 - C言語環境のキャッチアップ実施。
 - 手持ちの Mac が XCode 導入済で、 Clang を利用
 - vscode for mac で IDEデバッグ


## 準備
- [x]  XCode
- [x]  homebrew
- [x]  vscode

```
$ brew cask install visual-studio-code
```
- Cmd + Space -> visual studio code
- vscode上で) F1 -> install extensions
  - [x]  [C/C++](https://github.com/Microsoft/vscode-cpptools)

- vscode上で) F1 -> configure default build task

```
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "make",
            "type": "shell",
            "command": "make",
            "args": ["-j4", "debug"],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}
```

- [x]  ccache

```
$ brew install ccache
$ echo 'export PATH=/usr/local/opt/ccache/libexec:$PATH' >> ~/.profile
 # => .profile は自分のシェル用のprofile
```

- [x]  clang-format

```
$ brew install clang-format
$ clang-format -dump-config -style=Google > .clang-format
```

- vscode上で) F1 -> install extensions
  - [x]  [Clang-Format](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format)
- vscode上で) F1 -> open settings(JSON)

```
{
    "editor.formatOnSave": true
}
```

- [x]  cppcheck
- [x]  cunit
- [x]  tcmalloc(gperftools)
- [x]  valgrind

```
$ brew install cppcheck cunit gperftools valgrind
```

- vscode上で) F1 -> install extensions
  - [x]  [C/C++ Intellisense](https://github.com/austin-----/code-gnu-global)
    - F12, Shift+F12, Cmd+F12 など、タグジャンプ
- [x]  global 

```
$ xcode-select --install
$ brew install global
```

- vscode上で) F1 -> open settings(JSON)

```
{
     :
    "codegnuglobal.executable": "/usr/local/bin/global"
}
```

- vscode上で) F1 -> install extensions
  - [x]  [PlantUML](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml)

```
$ brew install plantuml
```

- vscode上で) F1 -> install extensions
  - [x]  [Markdown PDF](https://github.com/yzane/vscode-markdown-pdf/blob/master/README.ja.md)


## コード

### Makefile

 - vscode上で) F1 -> new file
 - ファイル名は Makefile

```

TARGET := a.out

MAIN_C := ./main.c
TEST_C := ./test.c
SRCS := $(filter-out $(TEST_C), $(wildcard ./*.c) $(wildcard ./**/*.c))
OBJS := $(SRCS:%.c=%.o)
DEPS := $(SRCS:%.c=%.d)
-include $(DEPS)

TSRCS := $(filter-out $(MAIN_C), $(wildcard ./*.c) $(wildcard ./**/*.c))
TOBJS := $(TSRCS:%.c=%.o)
TDEPS := $(TSRCS:%.c=%.d)
-include $(TDEPS)

.PHONY: release debug all check clean test

CFLAGS := -std=c17 -Weverything
CFLAGS_D :=-O0 -DDEBUG -g
CFLAGS_R :=-O2 -DNDEBUG

LDFLAGS :=-ltcmalloc
LDFLAGS_D :=-g -debug
LDFLAGS_R :=

all: CFLAGS+=$(CFLAGS_R)
all: LDFLAGS+=$(LDFLAGS_R)
all: clean $(TARGET)

debug: CFLAGS+=$(CFLAGS_D)
debug: LDFLAGS+=$(LDFLAGS_D)
debug: check $(TARGET)

CC := clang

.c.o:
	$(CC) -MMD -MP $(CFLAGS) -c $<

$(TARGET): $(OBJS)
	$(CC) $(LDFLAGS) -o $(TARGET) $(OBJS)

run: $(TARGET)
	valgrind --leak-check=full ./$(TARGET)

time: $(TARGET)
	time ./$(TARGET)

test: $(TARGET).cunit
	valgrind --leak-check=full ./$(TARGET).cunit

$(TARGET).cunit: $(TOBJS)
	$(CC) $(LDFLAGS) -lcunit -o $(TARGET).cunit $(TOBJS)

dSYM: $(TARGET)
	dsymutil $(TARGET)

tags:
	gtags -v

check:
	@for src in $(SRCS) ; do \
		clang-format -i "$$src" ; \
		cppcheck --enable=all --check-config "$$src" ; \
	done

clean:
	-rm -rf $(DEPS) $(OBJS) $(TDEPS) $(TOBJS) $(TARGET) $(TARGET).dSYM $(TARGET).cunit $(TARGET).cunit.dSYM

```

### usecase.puml

```
@startuml
User -> (Start)
@enduml
```

### main.c

 - vscode上で) F1 -> new file
 - ファイル名は main.c

```
#include <stdio.h>

#include "functions.h"

int main(int argc, char **argv) {
  say_hello();
}
```

### functions.h

 - vscode上で) F1 -> new file
 - ファイル名は functions.h

```
#pragma once
int say_hello(void);
```

### functions.c

 - vscode上で) F1 -> new file
 - ファイル名は functions.c

```
#include <stdio.h>

#include "functions.h"

int say_hello() {
  printf("hello world\n");
  return 0;
}
```

### test.c

 - vscode上で) F1 -> new file
 - ファイル名は test.c

```
#include "CUnit/Basic.h"
#include "CUnit/CUnit.h"

#include "functions.h"

void test_say_hello(void);

int main(void) {
  CU_pSuite testSuite;

  CU_initialize_registry();

  testSuite = CU_add_suite("ATestSuite", NULL, NULL);

  CU_add_test(testSuite, "test_say_hello", test_say_hello);

  CU_basic_set_mode(CU_BRM_VERBOSE);
  CU_basic_run_tests();

  CU_cleanup_registry();

  return 0;
}

void test_say_hello(void) { CU_ASSERT(say_hello() == 0); }

```

### a.out.cunit

 - vscode上で) F1 -> new terminal

```
$ make test
  :
./a.out.cunit


     CUnit - A unit testing framework for C - Version 2.1-3
     http://cunit.sourceforge.net/


Suite: ATestSuite
  Test: test_say_hello ...hello world
passed

Run Summary:    Type  Total    Ran Passed Failed Inactive
              suites      1      1    n/a      0        0
               tests      1      1      1      0        0
             asserts      1      1      1      0      n/a

Elapsed time =    0.000 seconds
```


### a.out

 - vscode上で) F1 -> run build
 - vscode上で) F1 -> new terminal

```
$ ./a.out
hello world
```

## デバッグ

 - vscode上で) F1 -> start debugging
    - 初回、設定の新規作成を促される。
    - "C++(gdb/lldb)"を選択してlaunch.json編集
 
```
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(lldb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/a.out", <==ここ
            "args": [],
            "stopAtEntry": true, <==ここ
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false, <==ここ
            "MIMode": "lldb"
        }
    ]
}
```

 - F5
    - main関数冒頭でブレイク。できました。