앞선 상황은 다음과 같다.
예상되는 행동: 빌드 완료
실행중:
[ 29%] Building CXX object filters/CMakeFiles/pcl_filters.dir/src/random_sample.cpp.o
[ 29%] Building CXX object filters/CMakeFiles/pcl_filters.dir/src/normal_space.cpp.o
Consolidate compiler generated dependencies of target pcl_pcd_introduce_nan
[ 29%] Linking CXX executable ../../bin/pcl_pcd_introduce_nan
/usr/bin/ld: ../../lib/libpcl_io.so.1.12.1.99: undefined reference to `boost::system::system_category()'
/usr/bin/ld: ../../lib/libpcl_io.so.1.12.1.99: undefined reference to `boost::system::generic_category()'
collect2: error: ld returned 1 exit status
make[2]: *** [io/tools/CMakeFiles/pcl_pcd_introduce_nan.dir/build.make:107: bin/pcl_pcd_introduce_nan] Error 1
make[1]: *** [CMakeFiles/Makefile2:1113: io/tools/CMakeFiles/pcl_pcd_introduce_nan.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
에러: 그냥 멈춤
우선, Consolidate compiler generated dependencies of target 이 행동을 왜 하는 지 알아보자.
통합 컴파일러가 타겟의 의존성 패키지들을 generated 했다고 한다. stakeoverflow에 검색해보니 많은 패키지들을 컴파일하는 과정에서 발견할 수 있었고, 하나의 실행파일(o, out ...)을 만들기 위해서 늘상 하는 행동같다.
그 아랫줄이 문제인데,
/usr/bin/ld: ../../lib/libpcl_io.so.1.12.1.99: undefined reference to `boost::system::system_category()'
바로 이 부분이다.
에러:
/home/ict-526/src/slam/pcl/kdtree/include/pcl/kdtree/impl/kdtree_flann.hpp:42:10: fatal error: flann/flann.hpp: No such file or directory
42 | #include <flann/flann.hpp>
| ^~~~~~~~~~~~~~~~~
compilation terminated.
해결책:
sudo apt-get install libflann-dev
undefined reference to `boost::system::system_category()'
똑같은 문제를 가진 이 사람은 우분투 11.10을 쓰고 있었고, 부스트 라이브러리를 1.46을 깔고 사용중이었는데, 똑같은 빌드하다가 똑같은 에러가 났다고 한다.
누군가가 바로 아래에 멘트를 남겼다.
That's not a compiler error, it's a linker error. You need to link to the Boost.System library
컴파일러 에러가 아닌, 링커에러이기 때문에 링크를 부스트.시스템 라이브러리로 걸어줘야 한다는 뜻이었다.
컴파일러 에러와 링커 에러가 구분되어있는줄도 몰랐다.
컴파일 에러는 문법이 틀려서 발생하는 에러로, 코드 자체가 실행이 안된다고 한다.
링커에러는..
흩어진 소스 코드 파일들을 컴파일한 뒤 각자 연결할 때 발생하는 에러입니다. 이름그대로..
예를 들어 어딘가에 선언되어 있는 헤더 파일이나 다른 코드 파일이 실제로는 존재하지 않을 때 이러한 오류가 나타납니다.
파일이 위치에 맞게 제대로 있는지, 선언하는 과정에서 또는 함수명에서 철자 등을 빼먹거나 오타를 낸 것은 아닌지 확인해봐야 합니다.
출처: https://woodforest.tistory.com/173 [나무 숲:티스토리]
그래서 해결책
The boost library you are using depends on the boost_system library. (Not all of them do.)
Assuming you use gcc, try adding -lboost_system to your compiler command line in order to link against that library.
-lboost_system 이라는 명령어를 컴파일러 명령어 줄에 추가하여 boost_system 라이브러리에 의존하는 나의 라이브러를 연결하는 것이다.
저 명령어는 무슨 뜻이고, 컴파일러 명령어 줄은 무엇인가?
g++나 gcc 명령어를 연습하다보면,
gcc -g test.o 나
gcc -g test.o -o (-g : 오브젝트 코드를 실행파일로 만들거나 -o 결과를 담을 파일을 지정)
g++ -o filename filename.cpp 이런 명령어 줄을 말하는데,
내가 시도하고 있는 pcl 라이브러리는 대부분의 프로젝트와 마찬가지로 make의 힘을 빌려서 복잡한 컴파일을 하고 있기 때문에, 컴파일 명령어 줄이 Makefile안에 들어가있다. 내 Makefile은 1298줄 짜리 코드다.
링킹 명령어를 g++ linker 옵션에 추가해줘야 한다. (또다른 검증 출처: https://tother.tistory.com/176) 이정도 기본적인 행위는 소스코드 상에서 되어있을 것이라는 생각도 든다.
컴파일 과정과 동적 라이브러리, 링킹에 관해서 잘 설명한 곳이다. https://www.lesstif.com/software-architect/shared-library-linker-loader-12943542.html
-lboost_system란 뭘까
공유 라이브러리(동적 라이브러리)
해당 파일이 동적 라이브러리(공유 라이브러리, shared library)를 사용했는지 확인하려면 file 명령어를 사용한다.
file a.out
동적 라이브러리를 사용했다면, LD_LIBRARY_PATH라는 종종 헤더파일이 뭉친 폴더 경로를 추가해야 했던 환경 변수에서 동적 라이브러리를 찾는다.
내가 설치하려는 프로그램에서 의존하는 동적라이브러리가 뭔지 알기 위해서는 ldd 를 사용한다.
Can't load library ...so 이런 식으로 에러가 뜨는 경우에....
ldd 실행파일 이름
not found가 표시된다면, /lib, /lib32, /lib64나 /usr/lib, /usr/lib32, /usr/lib64 에 해당하는 라이브러리가 있는 확인하자. 없을경우 실제로 라이브러리가 있는 위치(so파일이 있는 곳)을 LD_LIBRARY_PATH 에 추가해주면 된다.
링킹
ELF 포맷으로 되어있는 각 오브젝트를 하나의 오브젝트로 합치는 과정이다.(ELF_Executable and Linkable Format : 리눅스/유닉스 계열에서의 실행파일)
원래 명령어는 ld -o 실행파일 file1.o file2.o file3.o 와 같다.
라이브러리를 지정할 때에는 -l{lib_name}을 이용한다. 그래서 -lboost_system 같다.
그러면 -lboost_system을 어디에서 수정을 해줘야 할까?
그 전에, 우선 boost_system은 지금 깔린 boost에 있는 걸까?
sudo apt-get update
sudo apt-get install libboost-dev
이러고 실행했는데 안됐다.
sudo apt upgrade libboost-all-dev
똑같은 pcl 패키지를 github에서 소스코드를 받아서 까는 사람중에 나와 똑같은 에러를 질문한 사람을 찾았다.
https://github.com/PointCloudLibrary/pcl/issues/5249
해결책은
From that article(https://code-examples.net/en/q/cd7dc0), I gue았ss this is a linker problem. So I used the following commands, as follows.
sudo ln -s libboost_ system. so. 1.12.1 libboost_ system. so
It did solved my problem.
그래서 sudo ln -l libboost_system.so.1.12.1 libboost_system.so
로 바꿔서 했는데도 되질 않았다.
두 가지 원인이 있다. 우선, ln은 링킹을 하는 명령어인데, 전혀 존재하지 않는 파일에 대해서 바로가기를 만드는 링킹을 명령하고 있었다. 따라서 진짜 libboost_system.so.버전 파일을 찾아서 링킹을 해줘야 한다.
둘째로, 링킹을 한다고 문제가 해결되는 보장이 있는가?
다시말해서, 링킹(바로가기 만들기)를 해서 진짜 파일로부터 심볼링 링크로 만들어진 파일(libboost_system.so)가 이 컴파일러에서 찾으려고 애쓰던게 맞는지 확인하지 않았다.
두가지를 찾고 실제로 작동하는지도 앞으로 확인하겠다.