【问题标题】:CMake adding libraries for Windows/LinuxCMake 为 Windows/Linux 添加库
【发布时间】:2023-03-28 19:09:01
【问题描述】:

Visual Studio C++ 2008 / GCC 4.4.2

我已经编写了一个在 Linux 上运行的程序,现在我必须移植我的代码以在 Windows 上运行。我决定使用CMake,因为我想为两个平台保持相同的构建系统。

但是,我需要链接两个平台的一些库。在我的 CMakeLists.txt 我有以下内容:

# Compile with gcc c89 standard
IF(CMAKE_COMPILER_IS_GNUCXX)
    MESSAGE(STATUS "GCC detected - Adding compiler flags")
    SET(CMAKE_C_FLAGS "-pthread -ggdb -Wextra -Wall -pedantic -std=c89")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)

IF(WIN32)
SET(CMAKE_C_FLAGS "ws2_32.lib")
ENDIF(WIN32)

但是,当我在 Visual Studio 上编译时,出现以下错误:

fatal error C1083: Cannot open source file: 'ws2_32.lib': No such file or directory

我可以做些什么来解决这个问题?

========= 编辑 在顶级目录中

# Project Client Server
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

# Name of project
PROJECT(CLIENT_SERVER)

# Compile with gcc c89 standard
IF(CMAKE_COMPILER_IS_GNUCXX)
    MESSAGE(STATUS "GCC detected - Adding compiler flags")
    SET(CMAKE_C_FLAGS "-pthread -ggdb -Wextra -Wall -pedantic -std=c89")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)

IF(WIN32)
    SET(CMAKE_C_FLAGS "ws2_32")
ENDIF(WIN32)

# Includes
INCLUDE_DIRECTORIES(${CLIENT_SERVER_SOURCE_DIR}/cltsvr_ults)
INCLUDE_DIRECTORIES(${CLIENT_SERVER_SOURCE_DIR}/server)
INCLUDE_DIRECTORIES(${CLIENT_SERVER_SOURCE_DIR}/client)

# libraries
LINK_DIRECTORIES($CLIENT_SERVER/cltsvr_ults)

# Add subdirectories
ADD_SUBDIRECTORY(client)
ADD_SUBDIRECTORY(server)
ADD_SUBDIRECTORY(cltsvr_ults)
ADD_SUBDIRECTORY(test_client)
ADD_SUBDIRECTORY(test_server)

在客户端的子目录中我有这个 CMakeLists.txt

# libray called client from client.c
ADD_LIBRARY(client client)

在我创建和链接我的可执行文件的 test_clt 的子目录中。

# Test client add executable
INCLUDE_DIRECTORIES($CLIENT_SERVER_SOURCE_DIR/client)
INCLUDE_DIRECTORIES($CLIENT_SERVER_SOURCE_DIR/cltsvr_ults)

# Link the library
LINK_DIRECTORIES($CLIENT_SERVER/client)

# Add the executable 
ADD_EXECUTABLE(clt test_clt)

# Link the executable to the client library
IF(WIN32)
    TARGET_LINK_LIBRARIES(clt client ws2_32)
ENDIF(WIN32)

【问题讨论】:

  • 删除:IF(WIN32) SET(CMAKE_C_FLAGS "ws2_32") ENDIF(WIN32)
  • 那你太好了,我的回答低于+1,所以远离-1。

标签: cmake


【解决方案1】:

免责声明:我的回答具有哲学性质,应该鼓励您避免直接接触 CMAKE_C_FLAGS。对于刚刚解决您的问题的直接答案,请查看 Bill (the lead architect of the CMake btw.) 所写的内容。

关于 CMake 的事情是,它可以让您描述您想要做什么,而无需参考特定的编译器或平台。 CMake 所做的是根据您的使用构建编译器和链接器标志

  • include_directories
  • 添加定义
  • add_library
  • add_executable
  • target_link_libraries

如果没有外部依赖,除了编译器本身,这就是你所需要的。对于外部依赖项使用 查找包 它定义了一组变量,比如

  • find_package(SDL)

定义

  • SDL_INCLUDE_DIR
  • SDL_LIBRARY

分别用于 include_directories 和 target_link_libraries。 CMake 附带了一堆所谓的模块文件,比如 FindSDL.cmake 和许多其他可以用谷歌搜索的文件。

下一层是使用

  • 查找路径
  • find_library

在 Find???.cmake 模块本身中使用。

CMAKE_C_FLAGS 变量由 CMake 从这些命令组成。修改它意味着你绕过 CMake。在某些情况下,例如对于特殊优化标志,您想要这样做,但此时所有的权力和责任都从 CMake 转移给了您。

【讨论】:

  • 我的回答是否如此不恰当以至于应该给予负面评价?我应该删除它吗?
  • @MaikBeckmann 当您的编译器标志因平台而异但不是库差异的结果时,您有什么建议?例如,当我为 mingw 编译时,-fPIC 似乎没有必要......
  • @Davin 我猜你的意思是编译构建一个静态库,稍后链接到共享库,对吧? x86_32 Windows 和 Linux 不需要 -fPIC,但 x86_64 版本需要。
  • @Davin 一般来说,有许多层,其中较低的层会压倒较高的层。最低的(AFAIK)是源文件特定的标志,但我从未使用过。我经常使用你的是设置目标特定的标志。它是通过 SET_TARGET_PROPERTIES 完成的,您可以在其中设置 COMPILE_FLAGS 和/或 LINK_FLAGS 属性。这也是将 -fPIC 添加到静态库的正确位置,当您稍后想要将其链接到共享库时。
【解决方案2】:

通过将 ws2_32.lib 添加到 C_FLAGS,您是在编译时使用它,而不是在链接时使用它。如果您查看错误消息,您可以看到它将文件视为 c++ 源文件:无法打开源文件:'ws2_32.lib'。 target_link_libraries(target ws2_32) 应该可以工作。

【讨论】:

  • 我仍然遇到同样的问题。我用完整的 CMakeLists.txt 编辑了我的问题。你能看出什么不对吗?
【解决方案3】:

您需要使用Target Link Libraries 命令。目标将是您正在构建的可执行文件。

编辑: 您不应该在 C_FLAGS 中指定要链接的库。您可以执行 TARGET_LINK_LIBRARIES(execName, ws_32, ...) 之类的操作。我不是 100% 确定您是否需要 .lib。自从我使用 CMake 以来已经有一段时间了。

【讨论】:

    猜你喜欢
    • 2013-12-24
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多