카테고리 보관물: Tools & Tips

MacPorts: Orange3 Text Add-on 추가할 때 오류

오래된 Intel Mac은 Monterey이후 업데이트가 지원되지 않기 때문에 최신 버전의 Homebrew도 사용할 수가 없다. 이 때문에 MacPorts를 사용하는데 Orange3에 Text add-on을 설치를 시도할 때 Arch Linux에서와 같은 gensim버전 문제가 생겼다(참조: Arch Linux에서 Orange3 Text add-on 설치문제 해결).

2025년 10월 현재 최신버전인 gensim 4.3.3의 Python version 불일치 때문에 발생하는 문제인데, Arch Linux에서는 이 문제를 Python3.13대신 Python3.12의 가상환경을 만드는 것으로 해결 했었다.

MacPorts환경에서의 default python version을 확인해 보면 오래된 3.6을 가리키고 있는데, Python3.12를 설치해 준 다음 default python version을 3.12로 변경해서 이 문제를 해결할 수 있다.

먼저 MacPorts로 Python3.12를 설치해준다.

# Python3.12 설치
sudo port install python312

그리고 나서 default로 실행되는 python / python3 명령어를 Python3.12로 변경한다.

# python과 python3 명령어에 대한 인터프리터 지정
$ sudo port select --set python3 python312
Selecting 'python312' for 'python3' succeeded. 'python312' is now active.

$ sudo port select --set python python312 
Selecting 'python312' for 'python' succeeded. 'python312' is now active.

# 확인
$ port select --list python 
Available versions for python:
	none
	python312 (active)
	python313

이제, Orange3를 재실행하고 Text add-on을 추가하면 오류없이 설치되어 사용할 수 있다.

복붙의 함정, 디렉토리를 삭제할 수 없다?

매우 간단한 디렉토리 생성 명령어가 의도대로 동작하지 않고 실패했다. 왜 일까?

ls 명령어의 결과를 보면 알 수 있는데, 부모 디렉토리를 생성하는 -p 옵션이 동작하지 않고 디렉토리로 생성되어 버렸다. 그 다음으로 존재하지 않는 ~/docker/shared 디렉토리를 생성하려고 했으니 명령어가 실패한 것이다.

이 mkdir 명령어는 사실 어딘가에서 복사 붙여넣기 한 것인데, 이렇게 잘 못 생성된 디렉토리는 왠만해서 삭제가 되지 않는다.

rm -r "./-p"
rm -r -- "./-p"

그 이유는 -p에 붙어 있는 -가 ASCII가 아닌 Unicode U+2013이기 때문인데, 이를 삭제하려면 LC_ALL=C를 앞에 붙여서 임시로 Locale을 변경해 8진수로 표시되는 Unicode 값을 확인하고 그 이름으로 명령어를 입력 하면된다.

rm -r -- ''$'\342\200\223''p'

CMake FetchContent의 target이 중복되는 문제

CMake의 FetchContent는 빌드 과정까지 처리해 주기에 git-submodule 보다 편리한 방식인 것 같다. 다만, version 3.22.1 기준으로 여러 프로젝트 들이 동일한 target이름을 중복해서 선언하는 경우에는 이를 잘 처리 하지 못하고 위와 같은 에러를 뱉고 종료되는 문제가 있다.

-- Found systemd via pkg-config.
CMake Error at build/_deps/grpc-src/CMakeLists.txt:667 (add_custom_target):
  add_custom_target cannot create target "tools" because another target with
  the same name already exists.  The existing target is a custom target
  created in source directory
  "<absolute_path_to_the_build_dir>/_deps/vsomeip-src".
  See documentation for policy CMP0002 for more details.

위의 오류는 COVESA의 vsomeip project와 gRPC를 FetchContent로 구성하는 중에 발생한 것인데, 두 프로젝트 모두 “tools”라는 custom target을 선언하기 때문에 중복으로 오류가 발생한 것이다.

아쉽게도 현재로써는 깔끔하게 해결하는 방법은 없는 것 같고, 두 프로젝트 중 하나의 custom target 이름을 변경해서 중복되지 않도록 해 주는 패치를 작성해서 FetchContent의 PATCH_COMMAND에 인자로 넣어주는 방법으로 회피가 가능하다.

먼저 vsomeip project의 custom target인 tools를 vsomeip_tools로 변경하는 패치를 다음과 같이 작성하고 fix_custom_target.patch로 저장한다.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3501e02..0467426 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -654,7 +654,7 @@ add_subdirectory( examples/routingmanagerd )
 endif()
 
 # build tools
-add_custom_target( tools )
+add_custom_target( vsomeip_tools )
 add_subdirectory( tools )
 
 # build examples
-- 
2.34.1

다음으로 FetchConetnet에 PATCH_COMMAND argument를 명시한다.

# VSOME/IP
set(
    fix_custom_target
    git apply ${CMAKE_CURRENT_SOURCE_DIR}/fix_custom_target.patch
)
FetchContent_Declare(
    vsomeip
    GIT_REPOSITORY https://github.com/COVESA/vsomeip.git
    GIT_TAG <GIT_TAG>
    PATCH_COMMAND ${fix_custom_target}
)

FetchContent_MakeAvailable(vsomeip gRPC)

이제 cmake를 실행하면 patch가 적용되어 중복되는 target 이름 문제를 해결할 수 있다.

하지만 이 해결책은 아직 깔끔하진 않은데 그 이유는 처음 cmake를 실행하면 patch가 적용되면서 잘 되지만 두번째로 cmake를 실행 할 때는 이미 적용된 patch 때문에 git apply 명령어가 실패 하기 때문에 매번 patch가 적용된 directory(_deps/vsomeip-src)로 이동해서 git checkout -f를 실행해 주어야 하기 때문이다.

최종버전

git apply의 –reverse –check 옵션을 사용하면 패치가 적용되어 있는지 여부를 검사할 수 있으니 이 것을 이용해서 다음과 같은 간단한 shell script를 만들고 apply_patch_if_not.sh로 저장한다.

#!/usr/bin/env sh
# apply_patch_if_not.sh
# Apply given patch if not already applied.
#
#                         - Sep 2024, litcoder

if [ -z $1 ]; then
  echo "Usage: $0 <patch file path>"
  exit 1
fi

# Check if the patch was already applied.
git apply --reverse --check $1
if [ $? -eq 0 ]; then
  echo "The patch already applied, skip."
  exit 0
else
  # Apply the patch
  git apply $1
fi

이제 앞에서 작성한 FetchContent_Declare가 이 script를 부르도록 변경한다.

# VSOME/IP
set(
    fix_custom_target
    apply_patch_if_not.sh ${CMAKE_CURRENT_SOURCE_DIR}/fix_custom_target.patch
)
FetchContent_Declare(
    vsomeip
    GIT_REPOSITORY https://github.com/COVESA/vsomeip.git
    GIT_TAG <GIT_TAG>
    PATCH_COMMAND ${fix_custom_target}
)

FetchContent_MakeAvailable(vsomeip gRPC)