从相同的源代码创建单独的目标文件,并使用CMake链接到可执行文件

时间:2014-05-22 13:21:26

标签: visual-studio gcc makefile cmake

我有两个文件main.cpp和simd.cpp。我像这样编译它们:

g++ -c -mavx  -O3 simd.cpp -o simd_avx.o
g++ -c -msse2 -O3 simd.cpp -o simd_sse2.o
g++ -O3 main.cpp simd_avx.o simd_sse2.o

现在我想用Cmake构建它。这是我的CMakeLists.txt文件:

add_library(avx OBJECT simd.cpp)    
add_library(sse2 OBJECT simd.cpp)

IF(MSVC)    
    set(COMPILE_FLAGS "/openmp /Wall")    
    set_target_properties (avx PROPERTIES COMPILE_FLAGS "/arch:AVX")   
    set_target_properties (sse2 PROPERTIES COMPILE_FLAGS "/arch:SSE2 -D__SSE2__")    
    set(CMAKE_CXX_FLAGS ${COMPILE_FLAGS})    
    set(CMAKE_CXX_FLAGS_RELEASE "${COMPILE_FLAGS}")   
ELSE()    
    set(COMPILE_FLAGS "-fopenmp -Wall")    
    set_target_properties (avx PROPERTIES COMPILE_DEFINITIONS "-mavx")   
    set_target_properties (sse2 PROPERTIES COMPILE_DEFINITIONS "-msse2")    
    set(CMAKE_CXX_FLAGS ${COMPILE_FLAGS})    
    set(CMAKE_CXX_FLAGS_RELEASE "${COMPILE_FLAGS} -O3")   
ENDIF()
add_executable(dispatch main.cpp $<TARGET_OBJECTS:avx> $<TARGET_OBJECTS:sse2>)

使用MSVC2012,这很好用。但是,它在构建文件sse和avx中创建了两个单独的文件夹,每个文件夹指向相同的simd.cpp。我想这是一个很好的解决方案,因为我可以为每个文件夹单独设置属性。有两次显示相同的源文件有点烦人。

但是当我在Linux中为GCC创建一个makefile时,我得到错误:

<command-line>:0:1: error: macro names must be identifiers
make[2]: *** [src/CMakeFiles/avx.dir/simd.cpp.o] Error 1
make[1]: *** [src/CMakeFiles/avx.dir/all] Error 2
make: *** [all] Error 2

你能解释为什么Makefile失败了吗?你能建议一个更好的CMakeLists.txt文件来做我想做的事吗?

simd.cpp

#include <stdio.h>
#ifdef __AVX__ 
void func_avx() {
    printf("avx\n");
}
#elif defined ( __SSE2__ )
void func_sse2() {
    printf("sse2\n");
}
#else
// scalar code
#endif

的main.cpp

extern void func_sse2();
extern void func_avx();
       void func_dispatch();
void (*fp)() = &func_dispatch;

void func_dispatch() {
    #ifdef __AVX__
    fp = func_avx;
    #else
    fp = func_sse2;
    #endif
    fp();
}
void func() {
    fp();
}

int main() {
    func();
}

1 个答案:

答案 0 :(得分:2)

原因是印刷错误:

set_target_properties(avx PROPERTIES COMPILE_DEFINITIONS "-mavx")

编译器输出:

> cmake -H. -B_builds -DCMAKE_VERBOSE_MAKEFILE=ON
c++ -D-mavx ... 
In file included from <built-in>:
<command line>:1:9: error: macro names must be identifiers
#define -mavx 1

因此定义-mavx传递给编译器。

注释

  • 编译器标志同时来自CMAKE_CXX_FLAGSCMAKE_CXX_FLAGS_RELEASE(对于发布版本)。因此,如果CMAKE_CXX_FLAGS_RELEASE已经修改,则无需修改CMAKE_CXX_FLAGSedit #1
  • -O3选项已经传递给CMAKE_CXX_FLAGS_RELEASE,无需修改它(顺便提一下,你重写-DNDEBUG发布选项,我认为这非常重要): edit #2
  • 使用COMPILE_DEFINITIONS修改-D...标记(btw仅为msvc定义__SSE2__,是否正确?):edit #3
  • 重构点亮'位:edit #4
  • 现在你看到一个流行的CMake反模式:set(CMAKE_CXX_FLAGS "my flags")。默认情况下(有时根据用户需求)CMAKE_CXX_FLAGS 不是空变量,因此修改它的正确方法是:set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} my flags")edit #5
  • ...以及问题解决方法:final