带有 "MinGW Makefiles" 生成器的 cmake 之后的 mingw32-make 无法 link 可执行到对象库
mingw32-make following cmake with "MinGW Makefiles" generator fails to link executable to object library
我正在使用 CMake 来促进 C++ 项目的跨平台构建。使用相同的 CMakeLists.txt 文件,我成功完成了 Linux(生成 Unix Makefiles 以使用 g++ 编译)、OSX(生成 Unix Makefiles 以使用 clang++ 编译)和 Windows(为 Visual Studio 16 2019 生成)。
最近,我一直在 Windows 上使用 MinGW Makefiles 生成器测试构建过程。 CMake 生成 Makefile 没有任何问题。但是,当我在生成 Makefile 的目录中调用 mingw32-make
时,我开始 运行 出现问题。我能够将几个源文件编译到一个对象库中,但是当我尝试将 link print_graphs 可执行文件添加到该对象库时,我收到大量 multiple definition
方法错误对象库的第一个源文件,如下:
Scanning dependencies of target print_graphs
[ 52%] Building CXX object src/CMakeFiles/print_graphs.dir/print_graphs.cpp.obj
[ 57%] Linking CXX executable print_graphs.exe
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x6833): multiple definition of `roaring_bitmap_get_copy_on_write'
CMakeFiles\print_graphs.dir/objects.a(print_graphs.cpp.obj):print_graphs.cpp:(.text$roaring_bitmap_get_copy_on_write[roaring_bitmap_get_copy_on_write]+0x0): first defined here
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x6850): multiple definition of `roaring_bitmap_set_copy_on_write'
CMakeFiles\print_graphs.dir/objects.a(print_graphs.cpp.obj):print_graphs.cpp:(.text$roaring_bitmap_set_copy_on_write[roaring_bitmap_set_copy_on_write]+0x0): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$ra_get_index[ra_get_index]+0x0): multiple definition of `ra_get_index'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x65a1): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$ra_get_container_at_index[ra_get_container_at_index]+0x0): multiple definition of `ra_get_container_at_index'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x660e): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$roaring_bitmap_add_range[roaring_bitmap_add_range]+0x0): multiple definition of `roaring_bitmap_add_range'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x688e): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$roaring_bitmap_contains[roaring_bitmap_contains]+0x0): multiple definition of `roaring_bitmap_contains'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x690a): first defined here
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [src\CMakeFiles\print_graphs.dir\build.make:104: src/print_graphs.exe] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:933: src/CMakeFiles/print_graphs.dir/all] Error 2
mingw32-make: *** [Makefile:94: all] Error 2
在我的 src/ 目录下的 CMakeLists.txt 文件中,我有以下基本代码:
# Add header files:
set(HEADERS
${HEADERS_DIR}/cxxopts.h
${HEADERS_DIR}/roaring.h
${HEADERS_DIR}/roaring.hh
${HEADERS_DIR}/pugiconfig.h
${HEADERS_DIR}/pugixml.h
...
)
# Add object source files:
set(SOURCES
roaring.c
pugixml.cpp
...
)
# Combine the object source files into an object library:
add_library(objects OBJECT ${SOURCES} ${HEADERS})
# Point the build targets to their include directories:
target_include_directories(objects PRIVATE ${HEADERS_DIR})
# Add all executable scripts to be generated:
add_executable(program1 $<TARGET_OBJECTS:objects> program1.cpp )
# Point the build targets to their include directories:
target_include_directories(program1 PRIVATE ${HEADERS_DIR})
# Make sure the build targets are compiled with C++11:
target_compile_features(program1 PRIVATE cxx_std_11)
我是 CMake 的新手,所以我敢打赌这个问题是我在 CMakeLists.txt 文件中的错误形式。但是由于当我使用其他生成器时 CMake 能够毫无问题地构建所有内容,所以我不确定问题出在哪里。有谁知道是什么导致了 MinGW Makefiles 生成器的问题?
好的,我发现了问题,正如预期的那样,它在我的 CMake 中是错误的形式。在我的代码部分
# Combine the object source files into an object library:
add_library(objects OBJECT ${SOURCES} ${HEADERS})
不需要引用 ${HEADERS}
,因为在接下来的几行中明确建立了这种联系:
# Point the build targets to their include directories:
target_include_directories(objects PRIVATE ${HEADERS_DIR})
在最初的 add_library
调用中包含对头文件的引用似乎会导致头文件(或至少对它们的引用)的重复。
我仍然不确定为什么其他构建工具没有被这个问题绊倒,而 mingw32-make
是,但是在任何情况下维护正确的语法都是很好的,现在一切都按预期工作。
我正在使用 CMake 来促进 C++ 项目的跨平台构建。使用相同的 CMakeLists.txt 文件,我成功完成了 Linux(生成 Unix Makefiles 以使用 g++ 编译)、OSX(生成 Unix Makefiles 以使用 clang++ 编译)和 Windows(为 Visual Studio 16 2019 生成)。
最近,我一直在 Windows 上使用 MinGW Makefiles 生成器测试构建过程。 CMake 生成 Makefile 没有任何问题。但是,当我在生成 Makefile 的目录中调用 mingw32-make
时,我开始 运行 出现问题。我能够将几个源文件编译到一个对象库中,但是当我尝试将 link print_graphs 可执行文件添加到该对象库时,我收到大量 multiple definition
方法错误对象库的第一个源文件,如下:
Scanning dependencies of target print_graphs
[ 52%] Building CXX object src/CMakeFiles/print_graphs.dir/print_graphs.cpp.obj
[ 57%] Linking CXX executable print_graphs.exe
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x6833): multiple definition of `roaring_bitmap_get_copy_on_write'
CMakeFiles\print_graphs.dir/objects.a(print_graphs.cpp.obj):print_graphs.cpp:(.text$roaring_bitmap_get_copy_on_write[roaring_bitmap_get_copy_on_write]+0x0): first defined here
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x6850): multiple definition of `roaring_bitmap_set_copy_on_write'
CMakeFiles\print_graphs.dir/objects.a(print_graphs.cpp.obj):print_graphs.cpp:(.text$roaring_bitmap_set_copy_on_write[roaring_bitmap_set_copy_on_write]+0x0): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$ra_get_index[ra_get_index]+0x0): multiple definition of `ra_get_index'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x65a1): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$ra_get_container_at_index[ra_get_container_at_index]+0x0): multiple definition of `ra_get_container_at_index'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x660e): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$roaring_bitmap_add_range[roaring_bitmap_add_range]+0x0): multiple definition of `roaring_bitmap_add_range'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x688e): first defined here
CMakeFiles\print_graphs.dir/objects.a(set_cover_solver.cpp.obj):set_cover_solver.cpp:(.text$roaring_bitmap_contains[roaring_bitmap_contains]+0x0): multiple definition of `roaring_bitmap_contains'
CMakeFiles\print_graphs.dir/objects.a(roaring.c.obj):roaring.c:(.text+0x690a): first defined here
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [src\CMakeFiles\print_graphs.dir\build.make:104: src/print_graphs.exe] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:933: src/CMakeFiles/print_graphs.dir/all] Error 2
mingw32-make: *** [Makefile:94: all] Error 2
在我的 src/ 目录下的 CMakeLists.txt 文件中,我有以下基本代码:
# Add header files:
set(HEADERS
${HEADERS_DIR}/cxxopts.h
${HEADERS_DIR}/roaring.h
${HEADERS_DIR}/roaring.hh
${HEADERS_DIR}/pugiconfig.h
${HEADERS_DIR}/pugixml.h
...
)
# Add object source files:
set(SOURCES
roaring.c
pugixml.cpp
...
)
# Combine the object source files into an object library:
add_library(objects OBJECT ${SOURCES} ${HEADERS})
# Point the build targets to their include directories:
target_include_directories(objects PRIVATE ${HEADERS_DIR})
# Add all executable scripts to be generated:
add_executable(program1 $<TARGET_OBJECTS:objects> program1.cpp )
# Point the build targets to their include directories:
target_include_directories(program1 PRIVATE ${HEADERS_DIR})
# Make sure the build targets are compiled with C++11:
target_compile_features(program1 PRIVATE cxx_std_11)
我是 CMake 的新手,所以我敢打赌这个问题是我在 CMakeLists.txt 文件中的错误形式。但是由于当我使用其他生成器时 CMake 能够毫无问题地构建所有内容,所以我不确定问题出在哪里。有谁知道是什么导致了 MinGW Makefiles 生成器的问题?
好的,我发现了问题,正如预期的那样,它在我的 CMake 中是错误的形式。在我的代码部分
# Combine the object source files into an object library:
add_library(objects OBJECT ${SOURCES} ${HEADERS})
不需要引用 ${HEADERS}
,因为在接下来的几行中明确建立了这种联系:
# Point the build targets to their include directories:
target_include_directories(objects PRIVATE ${HEADERS_DIR})
在最初的 add_library
调用中包含对头文件的引用似乎会导致头文件(或至少对它们的引用)的重复。
我仍然不确定为什么其他构建工具没有被这个问题绊倒,而 mingw32-make
是,但是在任何情况下维护正确的语法都是很好的,现在一切都按预期工作。