微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 CMake 选项转换为预处理器定义的更简单/更简洁的机制?

如何解决将 CMake 选项转换为预处理器定义的更简单/更简洁的机制?

我发现自己在 CMakeLists.txt 中重复了以下代码段:

option(SOME_OPT "Some option" ON)
if (SOME_OPT)
    target_compile_deFinitions(my_app SOME_IDENTIFIER_HERE_RELATED_TO_OPT)
endif()

(偶尔也有类似的东西,但 -D 带有字符串值)。

CMake 中是否有一种机制(不要介意版本)使这更容易或更简洁?

解决方法

选项 1:使用生成器表达式

这是使用目标属性和生成器表达式的一种选择:

  "name": "aws-cdk-library","version": "0.0.0","description": "company's AWS CDK Library.","author": {
    "name": "company","url": "https://www.company.com","organization": true
  },"scripts": {
    "build": "lerna run build --stream --sort --concurrency=1","clean": "lerna clean","deploy": "lerna publish --no-push --no-git-tag-version --force-publish --yes","eslint": "eslint . --ext=.js,.ts --format=node_modules/eslint-formatter-pretty","install": "lerna bootstrap","lint": "eslint . --ext .js,.ts --ignore-path=.gitignore","package": "lerna run package --stream --sort --concurrency=1","publish-mvn": "lerna run publish-mvn --stream --sort --concurrency=1","test": "jest","test:ci": "jest --ci --runInBand","setVersion": "lerna version --no-push --no-git-tag-version --force-publish --yes","watch": "lerna run watch --parallel"
  },"devDependencies": {
    "@aws-cdk/assert": "1.106.0","@aws-cdk/aws-certificatemanager": "1.106.0","@aws-cdk/aws-cloudfront": "1.106.0","@aws-cdk/aws-cloudwatch": "1.106.0","@aws-cdk/aws-cloudwatch-actions": "1.106.0","@aws-cdk/aws-lambda": "1.106.0","@aws-cdk/aws-route53": "1.106.0","@aws-cdk/aws-route53-targets": "1.106.0","@aws-cdk/aws-s3": "1.106.0","@aws-cdk/aws-s3-deployment": "1.106.0","@aws-cdk/aws-sns": "1.106.0","@aws-cdk/aws-sns-subscriptions": "1.106.0","@aws-cdk/aws-synthetics": "1.106.0","@aws-cdk/core": "1.106.0","@aws-solutions-constructs/aws-cloudfront-s3": "1.106.0","@aws-solutions-constructs/core": "1.106.0","@types/jest": "^26.0.23","@types/node": "^15.0.0","@typescript-eslint/eslint-plugin": "^4.22.0","@typescript-eslint/parser": "^4.22.0","constructs": "^3.3.75","eslint": "^7.25.0","eslint-config-tc": "^19.0.0","eslint-config-typescript-tc": "^3.0.0","eslint-formatter-pretty": "^4.0.0","eslint-plugin-eslint-comments": "^3.2.0","eslint-plugin-import": "^2.22.1","eslint-plugin-jest": "^24.3.6","eslint-plugin-prettier": "^3.4.0","eslint-plugin-unicorn": "^33.0.0","jest": "^26.6.3","jsii": "^1.30.0","jsii-pacmak": "^1.30.0","jsii-release": "^0.2.9","lerna": "^4.0.0","prettier": "^2.2.1","ts-jest": "^26.5.5","ts-node": "^10.0.0","typescript": "^4.2.4"
  },"dependencies": {
    "@company/cdk-route53-cloudfront-s3": "file:packages/route53-cloudfront-s3","@company/cdk-cloudwatch": "file:packages/cloudwatch","@company/cdk-nodejs-canary": "file:packages/nodejs-canary","@company/cdk-pagerduty-alarm-action": "file:packages/pagerduty-alarm-action","@company/cdk-tags": "file:packages/tags"
  },"engines": {
    "node": ">=14.0.0","npm": ">=6.0.0"
  },"private": true,"license": "UNLICENSED"
}```

** module-package.json **

{
  "name": "@company/cdk-tags","description": "A helper library for setting required AWS Tags.","keywords": [
    "aws","cdk"
  ],"repository": {
    "type": "git","url": "git+................"
  },"url": "..........","license": "UNLICENSED","bugs": {
    "url": "..............."
  },"homepage": ".......................","main": "lib/index.js","types": "lib/index.d.ts","scripts": {
    "build": "jsii","watch": "jsii -w","package": "jsii-pacmak","publish-mvn": "jsii-release-maven"
  },"jsii": {
    "outdir": "dist","targets": {
      "java": {
        "package": "com.company.common.aws.cdk","maven": {
          "groupId": "com.company.common.aws.cdk","artifactId": "tags"
        }
      }
    }
  },"@aws-cdk/aws-sns": "1.106.0"
  },"peerDependencies": {
    "@aws-cdk/core": "1.106.0","constructs": "^3.2.84"
  }
}

如生成器表达式迷你语言所期望的那样,option(SOME_OPT1 "Some option 1" ON) option(SOME_OPT2 "Some option 2" OFF) option(SOME_OPT3 "Some option 3" ON) target_compile_definitions(my_app PRIVATE $<$<BOOL:${SOME_OPT1}>:SOME_IDENTIFIER_HERE_RELATED_TO_OPT1> $<$<BOOL:${SOME_OPT2}>:SOME_IDENTIFIER_HERE_RELATED_TO_OPT2> $<$<BOOL:${SOME_OPT3}>:SOME_IDENTIFIER_HERE_RELATED_TO_OPT3> ) 舞蹈对于将真实/虚假 CMake 值转换为 $<BOOL:${var}>1 是必要的。

选项 2:生成的“配置文件”

如果您有很多这样的选项,另一个选择是使用 0 命令创建包含相关信息的标题。创建一个名为 configure_file 的标题(作为示例),内容如下:

config.h.in

#ifndef MYPROJ_CONFIG_H #define MYPROJ_CONFIG_H #cmakedefine SOME_IDENTIFIER_HERE_RELATED_TO_OPT1 #cmakedefine SOME_IDENTIFIER_HERE_RELATED_TO_OPT2 #cmakedefine01 SOME_IDENTIFIER_HERE_RELATED_TO_OPT3 #endif 指令由 #cmakedefine VAR 处理以设置 configure_file,如果 VAR 在 CMakeLists.txt 中定义为真实的东西,如果不是,则注释掉该行。 VAR 变体始终定义 01,但将其设置为 VAR0

然后在你的 CMakeLists.txt 你可以写:

1

然后您的源文件可以option(SOME_OPT1 "Some option 1" ON) option(SOME_OPT2 "Some option 2" OFF) option(SOME_OPT3 "Some option 3" ON) # Setting these variables exposes them to configure_file below set(SOME_IDENTIFIER_HERE_RELATED_TO_OPT1 "${SOME_OPT1}") set(SOME_IDENTIFIER_HERE_RELATED_TO_OPT2 "${SOME_OPT2}") set(SOME_IDENTIFIER_HERE_RELATED_TO_OPT3 "${SOME_OPT3}") configure_file(config.h.in config.h) target_include_directories(my_app PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>") ,默认情况下:

#include <config.h>

这两个选项每个选项都需要一行开销,尽管第一种方法有点嘈杂,第二种方法需要一个文件。但是,第二种方法允许您添加额外的预处理器代码,这些代码可能更好地放在配置文件中。它还可以通过 #ifndef MYPROJ_CONFIG_H #define MYPROJ_CONFIG_H #define SOME_IDENTIFIER_HERE_RELATED_TO_OPT1 /* #undef SOME_IDENTIFIER_HERE_RELATED_TO_OPT2 */ #define SOME_IDENTIFIER_HERE_RELATED_TO_OPT3 1 #endif 语法替换 CMake 变量 values。有关更多详细信息,请参阅文档:https://cmake.org/cmake/help/latest/command/configure_file.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。