在开发中,如何将代码做到跨平台,如何保持 C/C++ 代码能够在多个平台上编译,是一个值得研究的问题。

此外,不同平台对某些操作有自己独特的优化,例如FFT(快速傅里叶变化)在 android 和 ios 上都有自己的独特的优化方式,如何在特定平台做优化,同样值得研究

混乱的 #ifdef

如何编写跨平台的代码呢?哥们,你脑袋里蹦出的第一个想法应该是使用:#ifdef

因此,你写的跨平台代码类似这样:
头文件

  1. void print_something();

源文件:

  1. #include "a.h"
  2. #ifdef _WIN32_
  3. void print_something()
  4. {
  5. printf("_WIN32_");
  6. }
  7. #ifdef _LINUX_
  8. void print_something()
  9. {
  10. printf("_LINUX_");
  11. }
  12. #ifdef _IOS_
  13. void print_something()
  14. {
  15. printf("_IOS_");
  16. }
  17. #ifdef _ANDROID_
  18. void print_something()
  19. {
  20. printf("_ANDROID_");
  21. }
  22. #endif

也许有成百上千处的代码充斥着这样一堆的#ifdef,说实话,自打我第一次看见这种实现方式时就觉得它不够优雅,它很混乱。

只编译特定平台的代码

更加优雅的方式就是:只编译特定平台的代码

利用 cmake 这样的工具,在 CMakeLists.txt 中,你知道你关心哪个平台,所以你可以只编译特定平台的. c/.cpp 文件,构建项目并忽略其他平台的代码。当你阅读代码的时候,就不用再看到一段的#ifdef了,因为他们被分成了不同的文件,这些文件永远都不会在同一个版本中冲突

因此,我可以构建一个头文件 a.h 和四个不同的. cpp 文件:a_win.cpp, a_linux.cpp, a_ios.cpp 和 a_android.cpp

然后在 CMakeLists.txt 中可以这么写:

  1. if(WIN32)
  2. FILE(GLOB PLATFORM_SOURCES *_win.cpp)
  3. elseif(LINUX)
  4. FILE(GLOB PLATFORM_SOURCES *_linux.cpp)
  5. elseif(IOS)
  6. FILE(GLOB PLATFORM_SOURCES *_ios.cpp)
  7. elseif(ANDROID)
  8. FILE(GLOB PLATFORM_SOURCES *_android.cpp)
  9. endif()
  10. add_library(a_lib ${PLATFORM_SOURCES})

这么做阅读和调整代码都非常简单,因为与平台相关的代码都单独放在一个文件中,比起原来丑陋的代码清晰了很多

Q&A

Q: 只有少量的跨平台代码也要用这种方式吗?
A: 不,如果只有少量的 #ifdef 并且不破坏代码的整洁,完全是可以接受的。因为我们的目的就是保持跨平台代码的整洁。

参考