CMake无法确定C++的链接器语言

142

我正在尝试在Windows 7 x64上使用Visual Studio 2010和Cygwin运行一个cmake hello world程序,但似乎两者都无法正常工作。我的目录结构如下:

HelloWorld
-- CMakeLists.txt
-- src/
-- -- CMakeLists.txt
-- -- main.cpp
-- build/

我执行 cd build 命令,然后执行 cmake .. 命令,但是出现了以下错误:

CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".
然而,如果我将main.cpp的扩展名更改为main.c,无论是在我的文件系统上还是在src / CMakeLists.txt中,一切都按预期工作。这适用于从Visual Studio命令提示符(Visual Studio解决方案生成器)和Cygwin终端(Unix Makefiles Generator)运行的情况。

有任何想法为什么这段代码不起作用吗?

CMakeLists.txt

PROJECT(HelloWorld C)
cmake_minimum_required(VERSION 2.8)

# include the cmake modules directory
set(CMAKE_MODULE_PATH ${HelloWorld_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})

add_subdirectory(src)

源代码目录下的 CMakeLists.txt 文件

# Include the directory itself as a path to include directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Create a variable called helloworld_SOURCES containing all .cpp files:
set(HelloWorld_SOURCES main.cpp)

# Create an executable file called helloworld from sources:
add_executable(hello ${HelloWorld_SOURCES })

主要代码/main.cpp

int main()
{
  return 0;
}

[...]如果我改变main.cpp的扩展名[...]你要将它改为什么?.cc吗? - JAB
糟糕,不小心漏掉了。我把它改成了'.c'。在原帖中进行了编辑。这让我几乎觉得可能没有C++编译器之类的东西,但是g++已经安装好了,而且Visual Studio对C++也不应该有问题。 - Chris Covert
PROJECT(HelloWorld C) 更改为 PROJECT(HelloWorld CXX)。C 和 C++ 是不同的编程语言。 - rustyx
10个回答

273

我也遇到了你提到的错误:

CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".

我的情况是由于存在扩展名为.cc的C++文件。

如果CMake无法正确确定代码语言,您可以使用以下方法:

set_target_properties(hello PROPERTIES LINKER_LANGUAGE CXX)
那个被接受的答案建议在project()语句后追加语言,这样可以更加严格地检查使用的语言(根据文档),但对我没有帮助:

你可以选择指定项目支持的语言。示例语言包括CXX(即C++)、C、Fortran等。默认启用C和CXX。例如,如果你没有C++编译器,你可以通过显式列出要支持的语言(例如C)来禁用它的检查。通过使用特殊的语言"NONE",可以禁用所有语言的检查。如果存在一个名为CMAKE_PROJECT__INCLUDE_FILE的变量,则指向该变量的文件将作为项目命令的最后一步被包含。


3
在我的情况下,我的文件扩展名为.hpp。这解决了问题! - brawner
对我来说,.hpp文件解决了这个问题。 - KulaGGin

111

在我的情况下,问题是目标文件中没有源文件。我的所有代码都是一个带有头文件中源代码的模板。添加一个空的 file.cpp 文件解决了这个问题。


9
“set target properties” 也适用于无 C++ 文件问题。 - Denise Skidmore
2
感谢您的提示。我也忘记将我的源代码移动到新创建的cmake项目(共享库)的相应src子目录中,这基本上是整个问题的原因。在这种情况下,人们真的很感激有向导来处理您的cmake项目结构。 :D - rbaleksandar
同样的原因在这里(复制粘贴错误)。谢谢! - Software Craftsman
6
实用提示:即使您的“库”仅包含头文件,也应创建一个.cpp文件并对每个文件进行#include。尽管在编译库时不会产生任何输出,但它将对您的文件进行语法检查,并检查您可能错过的头文件依赖项(例如系统头文件)。 - Mark Lakata
就是这么简单。路径中的拼写错误导致源文件中没有*.cpp文件。之后一切都好了。谢谢! - Rahul Das
3
我认为理论上正确的方法是将你的头文件库配置为一个INTERFACE库,并在该目标上设置接口包含目录到你头文件的位置。然后当你想在应用程序中使用它时(例如,你的测试应用程序,这将是可执行目标),你会“链接”它。这样做的好处是使安装变得微不足道,而且CMake甚至会为你生成可被其他项目find_package()找到的导出目标。 - jezza

60

18
这对我没有帮助。链接器错误仍然存在,请查看我的回答以了解修复方法。 - Joakim
是的,没错。我有一个main.cpp文件,即使它是纯C源代码,也应该使用PROJECT(HelloWorld CXX)。否则,会生成相同的错误。 - undefined

19

尽管可能让人感到困惑,但当项目中的cpp文件不存在时也会出现错误。

如果在CMakeLists.txt中列出源文件并错误地输入文件名,则会出现此错误。


2
这个答案是独立于其他答案的,因此它可以作为自己的答案。此外,这解决了我的问题。 - Czarking

18

我希望添加另一种解决方案,以便构建不带任何源文件的库。这种库也被称为“仅头文件”库。默认情况下,add_library需要至少添加一个源文件,否则会出现上述错误。由于仅头文件库非常常见,因此CMake使用INTERFACE关键字来构建此类库。如下所示使用INTERFACE关键字,它可以消除向库中添加空源文件的必要性。

add_library(myLibrary INTERFACE)
target_include_directories(myLibrary INTERFACE {CMAKE_CURRENT_SOURCE_DIR})

以上示例将创建一个仅包含与CMakeLists.txt文件位于同一目录中的所有头文件的头文件库。如果您的头文件不在与CMakeLists.txt文件相同的目录中,请使用路径替换{CMAKE_CURRENT_SOURCE_DIR}

请查看这篇博客文章CMake文档,了解有关头文件库和CMake的更多信息。


我会说这是正确的方法。 - itmuckel

8

虽然和问题不太相关,但这是给像我一样有类似问题的人的答案。

应用场景:Ubuntu(C、Clion、自动补全):

我遇到了同样的错误:

CMake 错误:无法确定目标“hello”的链接语言。

set_target_properties(hello PROPERTIES LINKER_LANGUAGE C) 可以帮助解决问题,但头文件没有加入到项目中,自动补全也无法正常工作。

这就是我的情况。

cmake_minimum_required(VERSION 3.5)

project(hello)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES ./)

add_executable(hello ${SOURCE_FILES})

set_target_properties(hello PROPERTIES LINKER_LANGUAGE C)

没有错误,但不是我需要的。我意识到将单个文件包含为源代码将使我获得自动完成,并且它还会将链接器设置为C

cmake_minimum_required(VERSION 3.5)

project(hello)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES ./1_helloworld.c)

add_executable(hello ${SOURCE_FILES})

2
刚刚注意到您正在使用CXX_FLAGS来设置C++标准版本,我想提一下CXX_STANDARD变量,我认为这是推荐的方式https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html,并且应该在cmake 3.5中可用。 - Chris Covert

2

在编译我的基于C语言的代码时,我也遇到了类似的错误。通过在我的cmake文件中更正源文件路径,我解决了这个问题。请检查cmake文件中提到的每个源文件的源文件路径。这可能也会对您有所帮助。


2

请检查源文件的路径(到相应的cpp文件)。


0

默认情况下,JNI本地文件夹的名称为jni。将其重命名为cpp即可解决问题。


-3

我成功解决了我的问题,通过改变

add_executable(file1.cpp)

add_executable(ProjectName file1.cpp)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接