2012-03-18 3 views
1

플랫폼 특정 코드를 조건부로 컴파일 한 후 multiple definition 링크 오류가 발생합니다.CMake로 링크 오류 받기

내 프로젝트는 다음과 같이 배치되어

: 내가 운영 체제를 감지하고 정의하기 위해 CMake에서 자기 반성을 설정

#if defined(LIBRARY_PLATFORM_LINUX) 
    #include "native/impl.linux.c" 
#elsif defined(LIBRARY_PLATFORM_WIN32) 
    #include "native/impl.win32.c" 
#endif 

다음 general.c 파일의 상단에

/ 
|__+ include/ 
| |__+ native/ 
| | |__ impl.h 
| | 
| |__ general.h 
| 
|__+ src/ 
    |__+ native/ 
    | |__ impl.linux.c 
    | |__ impl.win32.c 
    | 
    |__ general.c 

상응하는 상수. 문제는, 나는 모든 디렉토리에 하나 개 CMakeLists.txt 파일을 유지하고 싶지 않았다, 그래서 나는 단순히 모든 .c 파일을 as suggested in this answer을 globbed :

file(GLOB_RECURSE LIBRARY_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/*.c") 

분명히,이 문제를 일으키는 것입니다. 코드 #include d를 general.c에 컴파일하고 개별 파일 src/native/impl.*.c을 컴파일하는 것으로 보입니다.

CMakeFiles/lib.dir/src/native/impl.linux.c.o: In function `declared_in_impl_h': 
impl.linux.c:(.text+0x0): multiple definition of `declared_in_impl_h' 
CMakeFiles/lib.dir/src/general.c.o:general.c:(.text+0x0): first defined here 

어떻게 이런 상황을 풀 수 있습니까?

+0

'impl. *'파일에 다른 확장자를 사용하십시오. –

답변

2

이러한 종류의 크로스 플랫폼 상황에 대한 가장 좋은 관행은 Linux 용과 Windows 용의 두 가지 라이브러리를 만들고 조건부 포함을 중지하는 것입니다. 각 플랫폼은 관련 라이브러리 만 컴파일하고 링크합니다.

cmake로이를 수행하는 데 권장되는 방법은 globbing을 중지하고 각 파일을 포함하는 것입니다. 이 혼란에 빠지며 다시 컴파일해야한다는 것을 알지 못하는 경우가 있습니다. 변화가없는 레거시 코드가 그런 문제를 갖지 않을 것이라는 주장을 할 수 있습니다.

이 중 하나를 수행하지 않으려면 포함 된 코드를 c 파일 대신 헤더에 넣으십시오. 당신은 사람들이 정규 헤더처럼 사용되어야하는 것을 혼동하지 않도록 포함 경비원을 정말로 원하지 않습니다. 말한 행동에 대해서도 경고하라.

+0

나는 그것을 고려하지 않았다. 이제는 별도의 라이브러리가 훨씬 더 효율적으로 들립니다. 제발, 당신이 정교 할 수 있니? 동일한 프로젝트 내에서 구현 자체를 공유 라이브러리로 만드는 것이 합리적일까요? 그들은 정적으로 연결되어야 하는가? –

+0

@MatheusMoreira Hehe, 효율적이지 않습니다. 각 파일은 하나의 특정 작업을 수행하므로 진행중인 작업에 대한 혼란이 줄어 듭니다. 일반적으로 자신의 라이브러리에 각 구현을 넣은 다음 cmake에 둘 중 하나만 포함 시키십시오. 정적은 일반적으로 덜 움직이는 부분이지만 실제로는 중요하지 않습니다. 당신이 생각하는 것은 무엇이든간에 프로젝트에 가장 적합합니다. –

+0

@MatheusMoreira 저는 C++을 더 많이 사용하기 때문에 C에 대한 베스트 프랙티스가 과다 판매 될 수 있습니다. 나는 C로 까다로울 수있는 상황을 볼 수 있었다. –