ProtoBuf Link Error

Programming 2024. 7. 20. 16:14

또 이직을 하면서 이번에는 멀티 플랫폼에서 빌드를 하게 된다. 상황에 따라서 3가지 환경에서 빌드한다.

  • 맥북에서 원격으로 Raspberry Pi를 SSH로 연결 : 실환경
  • 맥북에서 MacOS Native : 실환경 없을 때 빌드 환경
  • 리눅스에서 크로스 컴파일 : CI를 위한 테스트 환경

그러다 보니 대부분 잘 돌아가는 데 희한한 경우를 만날 때가 있다.

이번에는 Linux, RB Pi에서는 잘 되는데, 맥에서만 안 된다.

에러는 갑자기 Link Error 가 난다.


Undefined symbols for architecture arm64:  
  "void absl::lts\_20240116::log\_internal::LogMessage::CopyToEncodedBuffer<(absl::lts\_20240116::log\_internal::LogMessage::StringType)0>(std::\_\_1::basic\_string\_view<char, std::\_\_1::char\_traits<char>>)", referenced from:  
      absl::lts\_20240116::log\_internal::LogMessage& absl::lts\_20240116::log\_internal::LogMessage::operator<<<19>(char const (&) \[19\]) in libproto.a\[2\](cw2.pb.cc.o)  
  "absl::lts\_20240116::log\_internal::LogMessage& absl::lts\_20240116::log\_internal::LogMessage::operator<<<unsigned long, 0>(unsigned long const&)", referenced from:  
      absl::lts\_20240116::log\_internal::LogMessage::operator<<(unsigned long) in libproto.a\[2\](cw2.pb.cc.o)

....

find_package를 CONFIG Mode로 돌렸더니, 이번에는 다른 에러가 난다. 이런 경우 대부분 버전이 안 맞는 거다.

MODULE 모드와 다른 에러가 나면, 설치된 Package와 Cmake에 설치된 파일이 불일치된 경우가 많다.

어쨌든 결론만 요약하면, 버전에 따라 Link될 라이브러리를 추가한다.
근원적인 다른 방법으로는 protobuf_generate_cpp 를 버전에 따라서 protobuf_generate로 교체하는 것인데,
뭐 굳이 필요한 게 아니라 그냥 넘어간다. 나중에 CMake의 버전이 올라가면 그 때 수정해야 겠다. 그 전에 하면 뭔가 일이 많아지니..


if (Protobuf_VERSION VERSION_GREATER_EQUAL 4)
    find_package(absl REQUIRED)

    target_link_libraries (${PROJECT_NAME}
            PUBLIC
            absl::log_internal_check_op
            ${PROTOBUF_LIBRARIES}
    )
    target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})
else()
    target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})
endif ()

WRITTEN BY
HanDDol
여행이란 건 말이지. 첫 걸음을 내딜 때는 모든 게 낯설고.. 그리고 점점 더 낯선 세상에 익숙해지면서 세상의 모든 곳이 고향처럼 느껴진다. 고향으로 돌아오는 여행의 마지막 걸음에는 나의 고향이 더 이상 익숙한 곳이 아닌 낯선 곳임을 알게 된다.

,

MacOS에서 간단한 gStreamer 파일을 실행하려는 데 애로 사항이 많네. 

 

컴파일까지야 어떻게든 했는데, 실행하려고 하니 에러가 발생하네. Dynamic Library를 찾지를 못 하는군. 

생성된 실행 파일을 `otool -L` 로 확인해 보니, gStreamer 의 참조 경로가 이렇게 되어 있네. 

 

```

 @rpath/libgstreamer-1.0.0.dylib (compatibility version 2205.0.0, current version 2205.0.0)

```

 

어쨌든, 원래는 /Library/Framework 폴더에 gStreamer가 복사되어 있는데. 해당 폴더는 또 Dynamic Library 경로에 추가되어 있지를 않고 있다. 뭐 나중을 위해서는 gStreamer Dynamic Library를 Application에 같이 패키징되어야 할 텐데, 디버깅/테스트할 때는 또 그걸 할 수 없으니. 

 

문제는 MacOS에서는 LD_LIBRARY_PATH가 동작하지 않는다. 찾아 보니 어쨌든 DYLD_FALLBACK_LIBRARY_PATH 에 추가하면 되네. Rust 나 Cargo 에서도 별 다른 방법은 없고. 환경 변수로 해당 폴더를 추가해주면 된다. 

 

실행하고 나면 참조되는 gObject 라이브러리 등이 중복되어 있다고 나오는데, 그건 무시하면 되고... 

 

그리고 나서는 다시 SSL Error가 발생하고, 이것 역시 Dynamic Library 경로 문제 같은데. 어쨌든 개발 시에만 발생할 문제로 보인다. 

 

GIO_EXTRA_MODULES 에 gstreamer 라이브러리의 gio/modules 를 할당해주면 문제 없이 실행된다. 


WRITTEN BY
HanDDol
여행이란 건 말이지. 첫 걸음을 내딜 때는 모든 게 낯설고.. 그리고 점점 더 낯선 세상에 익숙해지면서 세상의 모든 곳이 고향처럼 느껴진다. 고향으로 돌아오는 여행의 마지막 걸음에는 나의 고향이 더 이상 익숙한 곳이 아닌 낯선 곳임을 알게 된다.

,

2023. 3월 현재 기준으로.. 

 

여기 저기에 Conda를 사용해야 하네, 뭐네 여러가지 이야기가 많지만, 그건 작년 기준이고.

현재는 다음 TensorFlow 패키지만 설치한다. 

 

1. TensorFlow MacOS 버전 

   - tensorflow-macos => 2.10 

2. TensorFlow GPU 가속 

   - tensorflow-metal => 0.60 

 

이보다 높은 버전을 설치할 경우는 2.11의 변경 사항 때문에 GPU 가속이 동작하지 않는다. 

GPU 가속을 원하면 2.10, 0.60으로 버전을 맞추어야 한다. 

 

Apple Tensorflow 테스트 스크립트를 실행했을 때. 맥북 M2 기준으로 4배 정도 속도 차이가 난다. 

- CPU로 : 408초

- GPU로 : 90초 

 


WRITTEN BY
HanDDol
여행이란 건 말이지. 첫 걸음을 내딜 때는 모든 게 낯설고.. 그리고 점점 더 낯선 세상에 익숙해지면서 세상의 모든 곳이 고향처럼 느껴진다. 고향으로 돌아오는 여행의 마지막 걸음에는 나의 고향이 더 이상 익숙한 곳이 아닌 낯선 곳임을 알게 된다.

,