CMake 学习笔记(检测系统环境)

news/2024/10/18 12:19:38/

CMake 学习笔记(检测系统环境)

写C/C++程序时,尤其是我们的程序要能在不同的平台、操作系统下工作的时候。需要针对不同的环境写一些特定的代码。这时就需要CMake 根据不同的平台类型可以生成不同的项目文件。

CMake 在这方面做的很好。

检测当前的操作系统

cmake 通过一个变量 CMAKE_SYSTEM_NAME 记录当前操作系统的类型。不过这个记录的类型不是特别精细。我们无法分辨出当前的操作系统是 win 7 还是 win 10。

# set minimum cmake version
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)# project name, in this case no language required
project(recipe-01 LANGUAGES NONE)# print custom message depending on the operating system
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")message(STATUS "Configuring on/for Linux")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")message(STATUS "Configuring on/for macOS")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")message(STATUS "Configuring on/for Windows")
elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX")message(STATUS "Configuring on/for IBM AIX")
else()message(STATUS "Configuring on/for ${CMAKE_SYSTEM_NAME}")
endif()

在我这里输出的结果是:

-- Building for: Visual Studio 15 2017
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.22621.
-- Configuring on/for Windows
-- Configuring done
-- Generating done
-- Build files have been written to:

可以看到 cmake 检测出了当前的操作系统是 windows。

检测到了操作系统的信息,如何将信息传给我们的代码呢?这个也很简单,通过宏传进去就行了。下面是个例子。

#include <cstdlib>
#include <iostream>
#include <string>std::string say_hello() {
#ifdef IS_WINDOWSreturn std::string("Hello from Windows!");
#elif IS_LINUXreturn std::string("Hello from Linux!");
#elif IS_MACOSreturn std::string("Hello from macOS!");
#elsereturn std::string("Hello from an unknown system!");
#endif
}int main() {std::cout << say_hello() << std::endl;return EXIT_SUCCESS;
}
# set minimum cmake version
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)# project name and language
project(recipe-02 LANGUAGES CXX)# define executable and its source file
add_executable(hello-world hello-world.cpp)# let the preprocessor know about the system name
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")target_compile_definitions(hello-world PUBLIC "IS_LINUX")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")target_compile_definitions(hello-world PUBLIC "IS_MACOS")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")target_compile_definitions(hello-world PUBLIC "IS_WINDOWS")
endif()

这里最核心的是 cmake 的 target_compile_definitions 函数。

target_compile_definitions(hello-world PUBLIC "IS_WINDOWS")  

这句代码在编译 hello-world 文件时对象时传入了 IS_WINDOWS 这个宏。编译器可以通过检测这个宏来编译特定的代码。

检测使用的编译器

cmake 使用 CMAKE_CXX_COMPILER_ID 来标识当前使用的编译器的名称。下面是一个简单的例子。

#include <cstdlib>
#include <iostream>
#include <string>std::string say_hello() {
#ifdef IS_INTEL_CXX_COMPILER// only compiled when Intel compiler is selected// such compiler will not compile the other branchesreturn std::string("Hello Intel compiler!");
#elif IS_GNU_CXX_COMPILER// only compiled when GNU compiler is selected// such compiler will not compile the other branchesreturn std::string("Hello GNU compiler!");
#elif IS_PGI_CXX_COMPILER// etc.return std::string("Hello PGI compiler!");
#elif IS_XL_CXX_COMPILERreturn std::string("Hello XL compiler!");
#elif IS_MSVC_CXX_COMPILERreturn std::string("Hello MSVC compiler!");
#elsereturn std::string("Hello unknown compiler - have we met before?");
#endif
}int main() {std::cout << say_hello() << std::endl;std::cout << "compiler name is " COMPILER_NAME << std::endl;return EXIT_SUCCESS;
}
# set minimum cmake version
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)# project name and language
project(recipe-03 LANGUAGES CXX)# define executable and its source file
add_executable(hello-world hello-world.cpp)target_compile_definitions(hello-world PUBLIC "COMPILER_NAME=\"${CMAKE_CXX_COMPILER_ID}\"")# let the preprocessor know about the compiler vendor
if(CMAKE_CXX_COMPILER_ID MATCHES Intel)target_compile_definitions(hello-world PUBLIC "IS_INTEL_CXX_COMPILER")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES GNU)target_compile_definitions(hello-world PUBLIC "IS_GNU_CXX_COMPILER")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES PGI)target_compile_definitions(hello-world PUBLIC "IS_PGI_CXX_COMPILER")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES XL)target_compile_definitions(hello-world PUBLIC "IS_XL_CXX_COMPILER")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)target_compile_definitions(hello-world PUBLIC "IS_MSVC_CXX_COMPILER")
endif()
# etc ...

这里的代码和上一个有点不同:

if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)

其实也可以写为:

if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")

用 STREQUAL 时要记得加上双引号。

检测当前的CPU的指令集和位数

当前CPU 使用的指令集可以从 CMAKE_HOST_SYSTEM_PROCESSOR 得知,CMAKE_HOST_SYSTEM_PROCESSOR 只能得到主指令集的信息,扩展指令集比如 SSE 一类的要通过其他的手段来获得。

判断32位还是64位系统要用 CMAKE_SIZEOF_VOID_P 。CMAKE_SIZEOF_VOID_P 记录的是一个指针占用几个字节。占用4个字节就是32位系统,占用8个字节就是64位系统。

#include <cstdlib>
#include <iostream>
#include <string>#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)std::string say_hello() {std::string arch_info(TOSTRING(ARCHITECTURE));arch_info += std::string(" architecture. ");
#ifdef IS_32_BIT_ARCHreturn arch_info + std::string("Compiled on a 32 bit host processor.");
#elif IS_64_BIT_ARCHreturn arch_info + std::string("Compiled on a 64 bit host processor.");
#elsereturn arch_info + std::string("Neither 32 nor 64 bit, puzzling ...");
#endif
}int main() {std::cout << say_hello() << std::endl;return EXIT_SUCCESS;
}
# set minimum cmake version
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)# project name and language
project(recipe-04 LANGUAGES CXX)message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR is ${CMAKE_HOST_SYSTEM_PROCESSOR}" )
message(STATUS  "CMAKE_SIZEOF_VOID_P is ${CMAKE_SIZEOF_VOID_P}" )# define executable and its source file
add_executable(arch-dependent arch-dependent.cpp)# let the preprocessor know about the size of void *
if(CMAKE_SIZEOF_VOID_P EQUAL 8)target_compile_definitions(arch-dependent PUBLIC "IS_64_BIT_ARCH")message(STATUS "Target is 64 bits")
else()target_compile_definitions(arch-dependent PUBLIC "IS_32_BIT_ARCH")message(STATUS "Target is 32 bits")
endif()# let the preprocessor know about the host processor architecture
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i386")message(STATUS "i386 architecture detected")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i686")message(STATUS "i686 architecture detected")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64")message(STATUS "x86_64 architecture detected")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "AMD64")message(STATUS "AMD64 architecture detected")
else()message(STATUS "host processor architecture is unknown")
endif()target_compile_definitions(arch-dependentPUBLIC "ARCHITECTURE=${CMAKE_HOST_SYSTEM_PROCESSOR}")

检测当前的CPU 支持哪些扩展指令集

我们知道,CPU 经常会支持一些扩展指令集,比如 SSE、MMX 等。下面的代码可以检测当前的CPU 支持哪些扩展指令集。

# set minimum cmake version
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)# project name and language
project(recipe-05 LANGUAGES CXX)# define executable
add_executable(processor-info "")# and its source file
target_sources(processor-infoPRIVATEprocessor-info.cpp)# and its include directories
target_include_directories(processor-infoPRIVATE${PROJECT_BINARY_DIR})foreach(keyIN ITEMSNUMBER_OF_LOGICAL_CORESNUMBER_OF_PHYSICAL_CORESTOTAL_VIRTUAL_MEMORYAVAILABLE_VIRTUAL_MEMORYTOTAL_PHYSICAL_MEMORYAVAILABLE_PHYSICAL_MEMORYIS_64BITHAS_FPUHAS_MMXHAS_MMX_PLUSHAS_SSEHAS_SSE2HAS_SSE_FPHAS_SSE_MMXHAS_AMD_3DNOWHAS_AMD_3DNOW_PLUSHAS_IA64OS_NAMEOS_RELEASEOS_VERSIONOS_PLATFORM)cmake_host_system_information(RESULT _${key} QUERY ${key})
endforeach()configure_file(config.h.in config.h @ONLY)
#include "config.h"#include <cstdlib>
#include <iostream>int main() {std::cout << "Number of logical cores: " << NUMBER_OF_LOGICAL_CORES << std::endl;std::cout << "Number of physical cores: " << NUMBER_OF_PHYSICAL_CORES << std::endl;std::cout << "Total virtual memory in megabytes: " << TOTAL_VIRTUAL_MEMORY<< std::endl;std::cout << "Available virtual memory in megabytes: " << AVAILABLE_VIRTUAL_MEMORY<< std::endl;std::cout << "Total physical memory in megabytes: " << TOTAL_PHYSICAL_MEMORY<< std::endl;std::cout << "Available physical memory in megabytes: "<< AVAILABLE_PHYSICAL_MEMORY << std::endl;std::cout << "Processor is 64Bit: " << IS_64BIT << std::endl;std::cout << "Processor has floating point unit: " << HAS_FPU << std::endl;std::cout << "Processor supports MMX instructions: " << HAS_MMX << std::endl;std::cout << "Processor supports Ext. MMX instructions: " << HAS_MMX_PLUS<< std::endl;std::cout << "Processor supports SSE instructions: " << HAS_SSE << std::endl;std::cout << "Processor supports SSE2 instructions: " << HAS_SSE2 << std::endl;std::cout << "Processor supports SSE FP instructions: " << HAS_SSE_FP << std::endl;std::cout << "Processor supports SSE MMX instructions: " << HAS_SSE_MMX<< std::endl;std::cout << "Processor supports 3DNow instructions: " << HAS_AMD_3DNOW<< std::endl;std::cout << "Processor supports 3DNow+ instructions: " << HAS_AMD_3DNOW_PLUS<< std::endl;std::cout << "IA64 processor emulating x86 : " << HAS_IA64 << std::endl;std::cout << "OS name: " << OS_NAME << std::endl;std::cout << "OS sub-type: " << OS_RELEASE << std::endl;std::cout << "OS build ID: " << OS_VERSION << std::endl;std::cout << "OS platform: " << OS_PLATFORM << std::endl;return EXIT_SUCCESS;
}

在我的电脑上运行结果如下:

Number of logical cores: 16
Number of physical cores: 8
Total virtual memory in megabytes: 18500
Available virtual memory in megabytes: 5090
Total physical memory in megabytes: 15556
Available physical memory in megabytes: 7050
Processor is 64Bit: 1
Processor has floating point unit: 1
Processor supports MMX instructions: 1
Processor supports Ext. MMX instructions: 1
Processor supports SSE instructions: 1
Processor supports SSE2 instructions: 1
Processor supports SSE FP instructions: 0
Processor supports SSE MMX instructions: 1
Processor supports 3DNow instructions: 0
Processor supports 3DNow+ instructions: 0
IA64 processor emulating x86 : 0
OS name: Windows
OS sub-type:  Personal
OS build ID:  (Build 22621)
OS platform: AMD64

总结

最后总结一下:

  • CMAKE_SYSTEM_NAME 操作系统的名称
  • CMAKE_CXX_COMPILER_ID 编译器的名称
  • CMAKE_SIZEOF_VOID_P 指针的长度
  • CMAKE_HOST_SYSTEM_PROCESSOR 指令集类型

http://www.ppmy.cn/news/714137.html

相关文章

flutter mac环境配置

在 macOS 上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter一、配置flutter环境变量在 macOS 上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 解压文件放在我的文档里面 然后设置环境变量 1. 执…

KCC@成都首次非正式闭门会圆满成功

6月29日下午&#xff0c;KCC成都 召开了首次非正式闭门会&#xff0c;KCC 由开源社理事兼执行长庄表伟老师于2023年2月发起&#xff0c;全称 KAIYUANSHE City Community。本次会议由KCC成都站站长程诗杰主持召开&#xff0c;线下有唐云峰、水歌、肖伊、果汁、阿林等成都开源活跃…

C语言寻找第k小元素,小技巧——查找第k小的元素

今天分享一个小技巧&#xff0c;虽然是小技巧但是还是很有价值的&#xff0c;曾经是微软的面试题。题目是这样的&#xff0c;一个无序的数组让你找出第k小的元素&#xff0c;我当时看到这道题的时候也像很多人一样都是按普通的思维&#xff0c;先排序在去第K个&#xff0c;但是…

1的k次方一直加到n的k次方c语言,c语言函数求1到n的k次方和

#include #include /*----------------函数f2&#xff0c;求n的k次方-----------------*/ long f2(int n, int k) { long power n; /*power表示n的k次方*/ int i; for(i 1; i { power power*n; return power;/*将power作为f2的返回值*/ } } /*----------------函数f1&…

c语言编程最后j和k,C语言学习笔记:IJK运算,ijk,的,操作

表达式 i < j < k 在C语言中是合法的&#xff0c;但是它不是你所期望的意思。因为 &#xff1c; 运算符是左结合的&#xff0c; 所以这个表达式等价于 (i < j) < k . 换句话说&#xff0c; 表达式首先检测l.是否小千j, 然后用比较后产生的结果1或0来和K进行比较。 …

c语言学习-编写函数求组合数C= n! / (k! *( n-k)!)

编写函数求组合数C n! / (k! *( n-k)!) 程序流程图&#xff1a; 代码&#xff1a; #include<stdio.h> int mul(int x,int y); void main() { int n,k; double c; printf("please enter n:\tk:\t"); scanf("%d,%d",&n,&k); cmul(n,k); pr…

简洁解释k++,++k,k+1,k+=1的区别(附图)

以下为结合图进行说明 k和k两者都是递增1&#xff0c;但区别就在于k是先赋值给n再&#xff08;nk&#xff09;&#xff0c;而k是先后再赋值给n&#xff08;nk&#xff09;。 但两者不论是哪一种&#xff0c;区别也仅在于执行那一行&#xff0c;执行结束之后&#xff0c;对k来…

1的k次方到n的k次方

#include<stdio.h> #include<math.h> void sun(int k,int n) {int s0,i;for(i1;i<n;i)spow(i,k);printf("输出和是&#xff1a;%d\n",s); } int main() {int s0,k,n;printf("请输入两个整数K和N&#xff1a;\n");scanf("%d %d",&…