C++ Linux 代码破坏了 Windows 构建,因为缺少标头意味着函数未定义
Posted
技术标签:
【中文标题】C++ Linux 代码破坏了 Windows 构建,因为缺少标头意味着函数未定义【英文标题】:C++ Linux code breaks the Windows build because missing headers means the functions are undefined 【发布时间】:2017-12-21 16:25:58 【问题描述】:我正在使用 Windows 上的 Visual Studio 用 C++ 开发一个软件。从一开始,我就想让它在 Windows 和 Linux 上运行。显然,我不会在 Windows 机器上编译 Linux 二进制文件,但我还是想使用 Visual Studio 来编写代码。
当涉及到标头时,我根据预处理器定义选择要使用的文件。
一个非常初级和简单的例子:
#pragma once
#ifndef PLATFORM_TIMER_H
#define PLATFORM_TIMER_H
#ifdef _WIN32
#include "win32\win32_timer.h"
#elif __linux__
#include "linux\linux_timer.h"
#endif
#endif // PLATFORM_TIMER_H
对于标题,它工作得很好。但是用于 Linux 实现的 .cpp 文件会破坏 Windows 上的构建。这是因为 Linux .cpp 文件无论如何都会被编译,即使在 Windows 上也是如此。而且由于 Windows 机器缺少 Linux 头文件,它使用的函数将是未定义的。
问题1:处理这个问题的“行业标准”是什么?
问题 2:将 .h 和 .cpp 文件同时包装在“#ifdef PLATFORM”中以便代码仅在正确的操作系统上启用是否合理?
【问题讨论】:
#pragma once 在这里没用,您已经确定它只会使用 PLATFORM_TIMER_H 宏编译一次。另外,#pragma once 并不是通用的,尤其是当您进行跨平台时。 不相关,但为什么同时使用#pragma once
和旧式包含防护?编辑:只需阅读之前的评论。另外,我还没有遇到不知道如何处理#pragma once
的现代编译器。
你的反斜杠是错误的。把它们变成斜线。
@jbeck:两者都使用并非不合理。 “旧式”包含保护将涵盖#pragma once
可能失败的所有情况(例如,使用网络共享时不同路径上的相同文件),而#pragma once
可能会在正常情况下为您带来一点速度。就个人而言,我通常根本不理会#pragma once
。但是,我确实将生成的随机哈希添加到我的包含保护名称中。
【参考方案1】:
但用于 Linux 实现的 .cpp 文件会破坏 Windows 上的构建。这是因为 Linux .cpp 文件无论如何都会被编译,即使在 Windows 上也是如此。
为什么要为 Windows 构建编译特定于 Linux 的文件?
问题1:处理这个问题的“行业标准”是什么?
如果您要为特定于 Windows 的代码和特定于 Linux 的代码创建单独的源文件,那么重点就是在构建时只使用适合当前平台的源文件。
另一种方法是将两个实现放在同一个源文件中,使用条件编译来选择要使用的部分。这也很传统,尤其是在变化的部分小于整个函数的情况下。
问题 2:将 .h 和 .cpp 文件都包装在“#ifdef PLATFORM”中是否合理,以便代码只能在正确的操作系统上启用?
麻烦地创建单独的、特定于平台的源文件然后使用条件编译将它们全部包含在每个构建中是很奇怪的。它可以工作,但它不属于我个人对“合理”的定义。
【讨论】:
【参考方案2】:任何特定于一个操作系统的代码都需要正确设置#ifdef
,无论是在头文件还是源文件中。
【讨论】:
那么在#ifdefs 中包围源文件是不是很奇怪?感谢您及时回复!将尽快接受 @Markall 一点也不。要么这样,要么不要在 Windows 上编译 Linux 特定文件。 代码中的#ifdef
s 很脏,应避免使用,除非进行细微调整。实现应该分成单独的文件,大多数时候 2 个文件就足够了:一个用于 windows,另一个用于类 unix 系统。以上是关于C++ Linux 代码破坏了 Windows 构建,因为缺少标头意味着函数未定义的主要内容,如果未能解决你的问题,请参考以下文章
在 C、C++ 中检测 Windows 或 Linux [重复]
Windows 与 Linux 上的 gSOAP C++ 代码