레이블이 clang인 게시물을 표시합니다. 모든 게시물 표시
레이블이 clang인 게시물을 표시합니다. 모든 게시물 표시

clang complie_commands.json

# mac m1(arm64)에서 linux/x86(amd64) 환경 cpp 개발을 위해,
# 다음과 같이 docker 를 띄우고 host cpp 소스 경로 <-> docker볼륨을 연결했다. 
docker run -dit --name myproject \
    --hostname myproject-docker \
    --platform linux/amd64 \
    --workdir /myproject \
    -p 8080:8080 \
    -p 8081:8081 \
    -v /Users/ysoftman/myproject:/myproject \
    -v /Users/ysoftman/myproject_lib:/myproject_lib \
    ysoftman-myproject

# 빌드는 docker 에서 수행하도록 했다.
docker exec -u root -it myproject /bin/bash -c "
cd /myproject && 
    cmake \
    -DEXTERNS_DIR:PATH=/myproject_lib \
    -DCMAKE_INSTALL_PREFIX:PATH=/myproject/out
make -j8 && make install
"

# host 에서 cpp 를 nvim 으로 열면 다음과 같이 선어되지 않은 식별자 에러가 발생한다.
clang "use of undeclared identifier" 

# 참고로 vscode 는 자체 cpp intelligence 를 이용해서 에러가 없다.
# 원인은 nvim cpp LSP(LanguageServerProtocol) 로 clangd(clang 데몬)를 사용하고
# clangd 는 식별자 선언 내용을 compile_commands.json 파일을 참고하는데 이 파일이 없었다.
# 다음의 cmake 명령으로 compile_commands.json 을 생성할 수 있다.
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON {프로젝트 경로} 

# 문제
# 다음과 같이 host 기준으로 하면 이미 makefile, cmakecahe.txt 등의 파일들이 docker container 기준의 경로로 되어 있기 때문에 에러가 발생한다.
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON /Users/ysoftman/myproject

# 그리고 mac 루트 경로에서는 읽기만 허용해 다음과 같은 소프트 링크를 생성할 수 없었다.
ln -sf /myproject -> /Users/ysoftman/myproject

# 해결방법
# docker container 환경에서 compile_commands.json 생성하고
docker exec -u root -it myproject /bin/bash -c "
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON /myproject
"

# mac root 경로를 수정할 수 없어 compile_commands.json 의 경로를 수정한다.
pushd /Users/ysoftman/myproject
sed -i '' \
    -e "s#/myproject#$/Users/ysoftman/myproject#g" \
    -e "s#/myproject_lib#$/Users/ysoftman/myproject_lib#g" \
    compile_commands.json
popd

# 이제 nvim 으로 열어보면 에러도 없고 goto declaration도 잘 동작한다.

pip install gcc error

# pip 설치 중 다음과 같은 에러가 발생했다.
pip install cryptography
... 
/opt/homebrew/bin/gcc-13 -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -I/opt/homebrew/opt/zlib -I/opt/homebrew/opt/zlib -DFFI_BUILDING=1 -DUSE__THREAD -DHAVE_SYNC_SYNCHRONIZE -I/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/usr/include/ffi -I/Users/ysoftman/.pyenv/versions/3.12.0/include/python3.12 -c src/c/_cffi_backend.c -o build/temp.macosx-14.1-arm64-cpython-312/src/c/_cffi_backend.o -iwithsysroot/usr/include/ffi
...
gcc-13: error: unrecognized command-line option '-iwithsysroot/usr/include/ffi'

# 컴파일러를 clang 으로 변경하면 된다.
CC=clang pip install cryptography

# 참고로 python 환경을 보니 CC 가 gcc 로 설정되어 있었다.
# 예전 pyenv 로 python 설치시 clang 에 문제가 있어 gcc 로 변경해서 설치했던게 문제였다.
python -m sysconfig | rg 'CC = '
40:     CC = "/opt/homebrew/bin/gcc-13"
647:    LINKCC = "/opt/homebrew/bin/gcc-13"

replace intel app to apple app

mac intel -> M1(apple silicon)으로 마이그레이션 후
intel kind의 프로세서들은 rosetta2 에뮬레이터가 변환해서 apple silicon 에서도 동작한다.
하지만 변환과정으로 비효율적이다.
activity Monitor.app > kind 로 intel 프로세스를 확인할 수 있다.

아직 apple silicon(arm64) 바이너리가 많이 없지만 있다면 대체해보자.

# file 명령으로 바이너리가 어떤 환경에서 실행 되는지 알 수 있다.
file /bin/sh

# bin/zsh 는 arm64, x86_64 둘다 지원하는 universal binary 다.
file /bin/zsh

# intel 용으로 zsh 를 실행하기
arch -x86_64 /bin/zsh

# arm64 용으로 zsh 를 실행하기
arch -arm64 /bin/zsh

# 그런데 /usr/local/bin/zsh 는 x86_64 바이너리다.
file /usr/local/bin/zsh

# 아래 사이트에서 brew 설치 스크립트를 실행하면
# apple silicon 용(/opt/Homebrew/bin 에 설치) homebrew 로 설치 된다.
# 설후 설정을 보면 HOMEBREW_PREFIX: /opt/Homebrew 로 되어 있다.
brew config

# apple silicon 용 brew 등의 바이너리를 우선 실행할 수 있도록 한다.
export PATH=/opt/Homebrew/bin:$PATH

# 이제 쉘을 재시작하고 zsh 설치해 보자.
# bash 도 arm64 으로 설치하자.
brew install zsh bash

# 새로 설치된 zsh 는 arm64 버전이다.
which zsh
/opt/Homebrew/bin/zsh
file /opt/Homebrew/bin/zsh
/opt/Homebrew/bin/zsh: Mach-O 64-bit executable arm64

# 이제 brew 로 arm64 버전의 프로그램을 설치 할 수 있다.
brew install vim fzf git lsd wegt dog 등등

# 참고로 x86_64 용(/usr/local/bin 에 설치) brew 를 사용하려면
# x86_64 용(/usr/local/bin 에 설치) homebrew 설치하고
arch --x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/
install/HEAD/install.sh)"

# 다음과 같이 사용한다.
arch --x86_64 /usr/local/Homebrew/bin/brew install {패키지이름}

#####

arm64 zellij (/opt/Homebrew/bin/zellij) 0.39.1 을 사용하면 status-bar 등의 코드에서 에러가 발생한다.
SSE2 명령셋등 intel cpu 종속적인 코드가 있어 보인다.

# 당분간은 x86_64 zellij 사용하기 위해 arm64 로 설치된 zellij 는 제거한다.
brew uninstall zellij

# 몇주 후 0.39.2 버전이 나왔고 설치하니 해결되었다.
arch -arm64 brew install zellij

# 버전확인
/opt/homebrew/bin/zellij --version
zellij 0.39.2

# arm64 바이너리 확인
file /opt/homebrew/bin/zellij
/opt/homebrew/bin/zellij: Mach-O 64-bit executable arm64

#####

# 마이그레이션 후 파이썬 설치시
brew install python

# 또는 uname -m 이 x86_64 라면
arch -arm64 brew install python

# 다음과 같은 에러가 발생했다.
Error: An exception occurred within a child process:
  FormulaUnavailableError: No available formula with the name "/opt/Homebrew/Library/Taps/homebrew/homebrew-core/Aliases/python".

# 확인해보니 다음 경로 자체가 없었다.
/opt/Homebrew/Library/Taps/homebrew/homebrew-core

# homebrew/core 를 다시 구성후 설치하면 된다.
# 구성에 시간이 좀 걸린다.
brew tap homebrew/core

# 만약 /opt/Homebrew/Library/Taps/homebrew/homebrew-core 경로가 있는 상태에서도 안되면 삭제후 시도해보자.
rm -rf /opt/Homebrew/Library/Taps/homebrew/homebrew-core

#####

# 마이그레이션 후 
# pyenv 로 python 설치하면 다음과 같은 이유로 실패 한다.
pyenv install -v 3.12
ld: warning: duplicate -rpath '/Users/ysoftman/.pyenv/versions/3.12.0/lib' ignored
ld: warning: duplicate -rpath '/opt/homebrew/lib' ignored
ld: warning: search path '/Users/ysoftman/.pyenv/versions/3.12.0/lib' not found
ld: warning: search path '/Users/ysoftman/.pyenv/versions/3.12.0/lib' not found
ld: Undefined symbols:
ld: Undefined symbols:
  _libintl_bindtextdomain, referenced from:
      __locale_bindtextdomain in _localemodule.o
      __locale_bindtextdomain in _localemodule.o
  _libintl_dcgettext, referenced from:
      __locale_dcgettext in _localemodule.o
  _libintl_dgettext, referenced from:
      __locale_dgettext in _localemodule.o
  _libintl_gettext, referenced from:
      __locale_gettext in _localemodule.o
  _libintl_setlocale, referenced from:
      __locale_setlocale in _localemodule.o
      __locale_setlocale in _localemodule.o
      __locale_localeconv in _localemodule.o
      __locale_localeconv in _localemodule.o
      __locale_localeconv in _localemodule.o
      __locale_localeconv in _localemodule.o
  _libintl_textdomain, referenced from:
      __locale_textdomain in _localemodule.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Programs/_freeze_module] Error 1
make: *** Waiting for unfinished jobs....

# libintl.a 라이브러리에 있는 심볼들이 보인다.
# /opt/homebrew/lib/libintl.a 를 참조하지 않는게 문제 같다.
nm /opt/homebrew/lib/libintl.a | rg  "_libintl_(bindtextdomain|dcgettext|dgettext|gettext|setlocale)$"

# 구글링으로 여러 방법들을 시도...
# gettext library 를 찾지 못한다고 해서 다시 설치했지만 안된다.
brew reinstall gettext

# arm64 library 을 찾도록 LDFLAG 를 설정해도 안된다.
export LDFLAGS="-L/opt/homebrew/lib"
export CPPFLAGS="-I/opt/homebrew/include"

# 기존 x86_64 라이브러를 우선 참조하게 되는것 같아 해당 path 를 강제 삭제해도 안된다.
rm -rf /usr/local/Cellar/{gettext,readline}

# arm64 용으로 make gcc 등 컴파일러 최신으로 설치해도 안된다.
arch -arm64 brew install cmake make gcc

# 이번에는 실제 파이썬 소스를 다운받아 다음과 같이 빌드하면 잘된다.
# 아래처럼 configure 로 Makefile 이 생성하면 CC=gcc CXX=g++ 로 설정되어 있다.
git clone https://github.com/python/cpython
cd cpython; ./configure && make -j10

# pyenv 빌드시 clang (Apple clang version 15.0.0) 대신 
# 컴파일러를 gcc(없다면 설치 brew install gcc)로 변경하니 된다.
CC=/opt/homebrew/bin/gcc-13 pyenv install -v 3.12

# 몇달 후 zellij, /opt/homebrew 패키지들을 arm64 로 다시 설치등의 변화가 있었는데,
# 별도 CC 설정없이 clang (Apple clang version 15.0.0) 로도 됐다.
pyenv install -v 3.12

mac clang

# 맥은 gcc, g++ 등은 LLVM 기반의 clang 을 사용한다.
# c/c++ 컴파일러들은 모두 clang 을 사용하고 있다.
# 단순 링크를 보면 다음과 같다.
which -a gcc g++ clang llvm-g++ llvm-gcc cc c++ | grep -v "alias" | xargs ls -ahl
lrwxr-xr-x  1 root  wheel     7B 11 26 10:40 /usr/bin/c++ -> clang++
lrwxr-xr-x  1 root  wheel     5B 11 26 10:40 /usr/bin/cc -> clang
-rwxr-xr-x  1 root  wheel    18K  1 16 10:21 /usr/bin/clang
-rwxr-xr-x  1 root  wheel    18K  1 16 10:21 /usr/bin/g++
-rwxr-xr-x  1 root  wheel    18K  1 16 10:21 /usr/bin/gcc
lrwxr-xr-x  1 root  wheel     7B 11 26 10:40 /usr/bin/llvm-g++ -> clang++
lrwxr-xr-x  1 root  wheel     5B 11 26 10:40 /usr/bin/llvm-gcc -> clang

# 사용하는 프로그램과 라이브러리를 보면 gcc, g++ 도 clang 을 참조만 하고 있다.
gcc --print-search-dirs
install: /Library/Developer/CommandLineTools/usr/lib/llvm-gcc/4.2.1
programs: =/Library/Developer/CommandLineTools/usr/bin
libraries: =/Library/Developer/CommandLineTools/usr/lib/clang/10.0.0:/Library/Developer/CommandLineTools/usr/lib/llvm-gcc/4.2.1
llvm-gcc --print-search-dirs
programs: =/Library/Developer/CommandLineTools/usr/bin
libraries: =/Library/Developer/CommandLineTools/usr/lib/clang/10.0.0

ycmd server SHUT DOWN 에러 해결하기

# youcompleteme(ycm) 플러그인을 설치 후 vim 시작시 다음과 같은 에러가 발생한다.
# 참고로 ycm 은 클라이언트이고 third_party/ycmd 에 서버 소스가 있다.
The ycmd server SHUT DOWN (restart with ':YcmRestartServer')

# 다음과 같이 인스톨을 다시 해줘야 한다.
cd ~/.vim/plugged/youcompleteme
git submodule update --init --recursive
./install.py --all --verbose

# 만약 ./install.py 수행시 c++11 지원 안된다는 에러가 발생하는 경우
CMake Error at CMakeLists.txt:247 (message):
  Your C++ compiler does NOT fully support C++11.

# gcc 는 있지만 g++ 이 설치되어 있지 않아서다.
# 다음과 같이 g++ 를 설치 후 ./install.py
sudo yum install gcc-c++

# 만약 다음과 같은 에러가 발생하는 경우
fatal error: pyconfig.h:

# python-devel 을 설치 후 ./install.py
sudo yum install python-devel

#####

# M1(arm64) 맥북 환경에서 다음과 같이 빌드시 clang 에러가 발생했다.
./install.py --all --verbose

# 원인은 pyenv 로 설치한 python3.12(~/.pyenv/shims/python)가
# 설치시 다음과 같이 gcc 로 빌드해서였다.
CC=/opt/homebrew/bin/gcc-13 pyenv install -v 3.12

# clang 으로 다시 빌드해 설치 후
pyenv install -v 3.12

# ycmd 를 다시 빌드하면 된다.
./install.py --all --verbose

vscode c++ formatting

# vscode cpp extenstion 을 설치하고 코드 포맷팅을 하면 엉뚱하게 포맷팅이 된다.
# 이유는 포맷팅 환경이 설정되어 있지 않아서다.
# 우선 clang-format 을 설치하자.
brew install clang-format

# settings.json 을 열어 다음과 같이 설정한다.
"C_Cpp.clang_format_path": "/usr/local/bin/clang-format",

# file 이라고 명시하면 현재 프로젝트의 루트 경로의 .clang-format 파일을 읽어 들인다.
"C_Cpp.clang_format_style": "file",

# format_style 실패시 기본 셋팅(Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit)
"C_Cpp.clang_format_fallbackStyle": "Visual Studio"

# lazyvim(neovim)에서는 conform 플러그인에 cpp 포맷터로 clang-format 을 설정한다.
return {
  "stevearc/conform.nvim", -- For formatting
  opts = {
    -- formatters by file type
    formatters_by_ft = {
      cpp = { "clang-format" },
    },
  },
}

# 프로젝트 루트 위치에 .clang-format 파일을 다음과 같이 설정해 사용할 수 도 있다.
# 사용중인 .clang-format 파일
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 100
# BreakBeforeBraces: Allman # Always break before braces.
BreakBeforeBraces: Attach # Always attach braces to surrounding context.

# 참고로 현재 경로의 모든 c/cpp 파일 포맷팅 적용
# --style=file 로 지정하면 .clanf-format 파일을 참고한다.
# -i 옵션을 주면 변경된 스타일이 파일에 적용된다.
fd ".c$|.cpp$" --exec clang-format --style=file -i

# 포맷 스타일 결과 비교, main 함수만 발췌
# 개인적으로 visualstudio 또는 google 스타일이 좋은것 같다.

# Visual Studio 는 Clang-format 기본스타일 종류에는 없고 다음과 같이 설정해야한다.
# clang-format --style="{UseTab: Never,IndentWidth: 4,
BreakBeforeBraces: Allman,
AllowShortIfStatementsOnASingleLine: false,
IndentCaseLabels: false,
ColumnLimit: 0}" hello_world.cpp
# 들여쓰기 탭, 시작 중괄호 한줄 차지
int main()
{
    string a = "1";
    if (a == "1")
    {
        cout << "hello world" << endl;
    }
    return 0;
}

# clang-format --style="google" hello_world.cpp
# 들여쓰기 공백2, 시작 중괄호 같은 라인에 시작
int main() {
  string a = "1";
  if (a == "1") {
    cout << "hello world" << endl;
  }
  return 0;
}

# clang-format --style="webkit" hello_world.cpp
# 들여쓰기 공백4, 함수 시작 중괄호만 한줄, 함수내에서는 같은 라인에 시작
int main()
{
    string a = "1";
    if (a == "1") {
        cout << "hello world" << endl;
    }
    return 0;
}

# clang-format --style="mozilla" hello_world.cpp
# 들여쓰기 공백2, 함수 시작 중괄호만 한줄, 함수내에서는 같은 라인에 시작
# 함수 리턴 타임 한줄 차지
int
main()
{
  string a = "1";
  if (a == "1") {
    cout << "hello world" << endl;
  }
  return 0;
}