【问题标题】:Create separate object files from the same source code and link to an executable with CMake从相同的源代码创建单独的目标文件并使用 CMake 链接到可执行文件
【发布时间】:2014-05-22 13:21:25
【问题描述】:

我有两个文件 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();
}

【问题讨论】:

  • &lt;command-line&gt;:0:1: error: macro names must be identifiers 命令行参数中发生了不好的事情?
  • 为什么你使用COMPILE_DEFINITIONS for linux 而COMPILE_FLAGS for msvc?
  • 嘿!谢谢!你解决了。多么令人尴尬:-/ COMPILE_FLAGS 已定义,但未定义 COMPILE_DEFINTIONS。我将 COMPILE_DEFINTIONS 更改为 COMPILE_FLAGS 并且它可以工作。我昨天开始使用cmake。希望我对此有一些警告!我原本打算这篇文章只是关于 Visual Studio 的,而我在这篇文章中只在 Linux 上测试了 GCC。无论如何,这是一个好的解决方案吗?如果您有更好的解决方案,可以发布吗?
  • 有什么方法可以让 Cmake 警告我未定义的变量,以帮助避免将来出现此类错误?我只是尝试使用随机名称,它使 Makefile 没有任何警告。
  • is this a good soltuion 我认为它非常适合这种任务。如果您愿意,我有一些代码审查的想法,我可以将其作为答案)

标签: visual-studio gcc makefile cmake


【解决方案1】:

原因是印刷错误:

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_FLAGS 和CMAKE_CXX_FLAGS_RELEASE(用于发布版本)。所以如果CMAKE_CXX_FLAGS已经修改,则无需修改CMAKE_CXX_FLAGS_RELEASE:edit #1
  • -O3 选项已经传递给 CMAKE_CXX_FLAGS_RELEASE 不需要修改它(顺便说一句,你重写 -DNDEBUG 释放选项,我认为这很重要): edit #2
  • 使用COMPILE_DEFINITIONS 修改-D... 标志(顺便说一句,您只为msvc 定义__SSE2__,对吗?):edit #3
  • 重构 lit' 位:edit #4
  • 现在您会看到一种流行的 CMake 反模式:set(CMAKE_CXX_FLAGS "my flags")。默认情况下(有时根据用户需要)CMAKE_CXX_FLAGS 是 not 空变量,因此修改它的正确方法是:set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} my flags"): edit #5
  • ... 和问题修复:final

【讨论】:

  • 这是一个很好的答案!谢谢!我从中学到了很多,这将为我在学习 Cmake 时节省大量时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
  • 2019-07-11
相关资源
最近更新 更多