├── .appveyor.yml ├── .clang-format ├── .gitignore ├── .gitmodules ├── .vscode ├── launch.json └── tasks.json ├── CMakeLists.txt ├── CMakeSettings.json ├── LICENSE ├── README.md ├── app.json ├── app_id.txt ├── cmake ├── Modules │ ├── FindVcpkgIncludeDir.cmake │ ├── FixDebugLibraryLookup.cmake │ ├── FixLinkConflict.cmake │ └── cotire.cmake └── x86-windows-static-custom.cmake ├── scripts ├── build.ps1 ├── clean.ps1 ├── generate.ps1 ├── helpers.ps1 ├── post_build.ps1 ├── prepare.ps1 ├── prepare_prebuilt.ps1 └── vcpkg.ps1 ├── src └── demo.cpp └── vcpkg-requirements.txt /.appveyor.yml: -------------------------------------------------------------------------------- 1 | branches: 2 | except: 3 | - /dev.*/ # do not build dev branch 4 | 5 | image: 6 | - Visual Studio 2019 7 | 8 | platform: 9 | - x86 10 | 11 | configuration: 12 | - Debug 13 | - Release 14 | 15 | environment: 16 | VCPKG_ROOT: C:\tools\vcpkg 17 | 18 | install: 19 | - git submodule init 20 | - git submodule update 21 | - powershell .\scripts\prepare.ps1 22 | - set /p APP_ID=") 44 | -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "environments": [ 3 | { 4 | "VCPKG_ROOT": "${projectDir}\\vcpkg", 5 | "VCPKG_CMAKE": "${env.VCPKG_ROOT}\\scripts\\buildsystems\\vcpkg.cmake", 6 | "VCPKG_TRIPLET": "x86-windows-static-custom" 7 | } 8 | ], 9 | "configurations": [ 10 | { 11 | "name": "Debug", 12 | "generator": "Visual Studio 16 2019", 13 | "configurationType": "Debug", 14 | "inheritEnvironments": [ 15 | "msvc_x86" 16 | ], 17 | "buildRoot": "${projectDir}\\build\\${name}", 18 | "cmakeCommandArgs": "-T v142 -DCMAKE_BUILD_TYPE=${name}", 19 | "buildCommandArgs": "", 20 | "ctestCommandArgs": "", 21 | "variables": [ 22 | { 23 | "name": "CMAKE_TOOLCHAIN_FILE", 24 | "value": "${env.VCPKG_CMAKE}" 25 | }, 26 | { 27 | "name": "VCPKG_TARGET_TRIPLET", 28 | "value": "${env.VCPKG_TRIPLET}" 29 | } 30 | ] 31 | }, 32 | { 33 | "name": "Release", 34 | "generator": "Visual Studio 16 2019", 35 | "configurationType": "Release", 36 | "inheritEnvironments": [ 37 | "msvc_x86" 38 | ], 39 | "buildRoot": "${projectDir}\\build\\${name}", 40 | "cmakeCommandArgs": "-T v142 -DCMAKE_BUILD_TYPE=${name}", 41 | "buildCommandArgs": "", 42 | "ctestCommandArgs": "", 43 | "variables": [ 44 | { 45 | "name": "CMAKE_TOOLCHAIN_FILE", 46 | "value": "${env.VCPKG_CMAKE}" 47 | }, 48 | { 49 | "name": "VCPKG_TARGET_TRIPLET", 50 | "value": "${env.VCPKG_TRIPLET}" 51 | } 52 | ] 53 | } 54 | ] 55 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2017 Richard Chien 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoolQ C++ SDK 2 | 3 | 7 | 8 | **本项目为旧版 CoolQ C++ SDK,已不再维护,请使用新版,见 [cqmoe/cqcppsdk](https://github.com/cqmoe/cqcppsdk)。** 9 | 10 | CoolQ C++ SDK 封装了跟 DLL 接口相关的底层逻辑,包括: 11 | 12 | - 将所有从 酷Q 传来的字符串转成 UTF-8,并将所有传入 酷Q 的字符串转成 GB18030 13 | - 封装了 `Message` 和 `MessageSegment` 类,使构造消息内容更为方便 14 | - `MessageSegment` 类提供了快速构造消息段(CQ 码)的接口 15 | - 处理了消息内容中的 emoji 到 Unicode 的转换 16 | - 封装了 酷Q 事件的数据,在事件处理函数中传入 17 | - 将 QQ 相关的事件分为三个大类别:`MessageEvent`、`NoticeEvent`、`RequestEvent` 18 | - 封装了数据类,如 `User`、`Group`、`GroupMember` 等 19 | - …… 20 | 21 | 并且对外提供了更现代的 C++ 接口,从而为更方便地编写插件提供可能。 22 | 23 | ## 目录 24 | 25 | - [CoolQ C++ SDK](#coolq-c-sdk) 26 | - [目录](#%e7%9b%ae%e5%bd%95) 27 | - [示例](#%e7%a4%ba%e4%be%8b) 28 | - [使用方式](#%e4%bd%bf%e7%94%a8%e6%96%b9%e5%bc%8f) 29 | - [预备](#%e9%a2%84%e5%a4%87) 30 | - [下载 SDK](#%e4%b8%8b%e8%bd%bd-sdk) 31 | - [准备构建环境](#%e5%87%86%e5%a4%87%e6%9e%84%e5%bb%ba%e7%8e%af%e5%a2%83) 32 | - [修改 App Id 和相关信息](#%e4%bf%ae%e6%94%b9-app-id-%e5%92%8c%e7%9b%b8%e5%85%b3%e4%bf%a1%e6%81%af) 33 | - [编写功能](#%e7%bc%96%e5%86%99%e5%8a%9f%e8%83%bd) 34 | - [构建项目](#%e6%9e%84%e5%bb%ba%e9%a1%b9%e7%9b%ae) 35 | - [安装插件到 酷Q](#%e5%ae%89%e8%a3%85%e6%8f%92%e4%bb%b6%e5%88%b0-%e9%85%b7q) 36 | - [更新 SDK](#%e6%9b%b4%e6%96%b0-sdk) 37 | - [安装依赖](#%e5%ae%89%e8%a3%85%e4%be%9d%e8%b5%96) 38 | - [固定依赖包版本](#%e5%9b%ba%e5%ae%9a%e4%be%9d%e8%b5%96%e5%8c%85%e7%89%88%e6%9c%ac) 39 | - [使用 CI 自动构建](#%e4%bd%bf%e7%94%a8-ci-%e8%87%aa%e5%8a%a8%e6%9e%84%e5%bb%ba) 40 | - [分发应用](#%e5%88%86%e5%8f%91%e5%ba%94%e7%94%a8) 41 | - [插件生命周期](#%e6%8f%92%e4%bb%b6%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f) 42 | - [应用案例](#%e5%ba%94%e7%94%a8%e6%a1%88%e4%be%8b) 43 | 44 | ## 示例 45 | 46 | ```cpp 47 | #include "cqsdk/cqsdk.h" 48 | 49 | // namespace cq::app 包含插件本身的生命周期事件和管理 50 | // namespace cq::event 用于注册 QQ 相关的事件处理函数 51 | // namespace cq::api 用于调用酷 Q 提供的接口 52 | // namespace cq::logging 用于日志 53 | // namespace cq::message 提供封装了的 Message 等类 54 | 55 | // 插件入口,在静态成员初始化之后,app::on_initialize 事件发生之前被执行,用于配置 SDK 和注册事件回调 56 | CQ_MAIN { 57 | cq::app::on_enable = [] { 58 | // cq::logging、cq::api、cq::dir 等命名空间下的函数只能在事件回调函数内部调用,而不能直接在 CQ_MAIN 中调用 59 | cq::logging::debug(u8"启用", u8"插件已启动"); 60 | }; 61 | 62 | cq::event::on_private_msg = [](const cq::PrivateMessageEvent &e) { 63 | cq::logging::debug(u8"消息", u8"收到私聊消息:" + e.message + u8",发送者:" + std::to_string(e.user_id)); 64 | 65 | if (e.user_id != 1002647525) return; 66 | 67 | try { 68 | cq::api::send_private_msg(e.user_id, e.message); // echo 回去 69 | 70 | cq::api::send_msg(e.target, e.message); // 使用 e.target 指定发送目标 71 | 72 | // MessageSegment 类提供一些静态成员函数以快速构造消息段 73 | cq::Message msg = cq::MessageSegment::contact(cq::MessageSegment::ContactType::GROUP, 201865589); 74 | msg.send(e.target); // 使用 Message 类的 send 成员函数 75 | } catch (const cq::exception::ApiError &err) { 76 | // API 调用失败 77 | cq::logging::debug(u8"API", u8"调用失败,错误码:" + std::to_string(err.code)); 78 | } 79 | 80 | e.block(); // 阻止事件继续传递给其它插件 81 | }; 82 | 83 | cq::event::on_group_msg = [](const auto &e /* 使用 C++ 的 auto 关键字 */) { 84 | const auto memlist = cq::api::get_group_member_list(e.group_id); // 获取数据接口 85 | cq::Message msg = u8"本群一共有 "; // string 到 Message 自动转换 86 | msg += std::to_string(memlist.size()) + u8" 个成员"; // Message 类可以进行加法运算 87 | cq::message::send(e.target, msg); // 使用 message 命名空间的 send 函数 88 | }; 89 | } 90 | ``` 91 | 92 | 更多请看 [src/demo.cpp](src/demo.cpp)。 93 | 94 | ## 使用方式 95 | 96 | ### 预备 97 | 98 | 本项目使用 [CMake](https://cmake.org/) 构建,依赖项通过 [vcpkg](https://github.com/Microsoft/vcpkg) 管理。如果你没有使用过这两个工具,请先前往它们的官方网站了解基本用法。 99 | 100 | 在开始使用之前,请确保你已经安装了 Git,且 `PATH` 中存在 `git` 命令。不需要安装 vcpkg,后面的脚本中会自动安装。 101 | 102 | 构建脚本要求 PowerShell 5+,如果系统是 Windows 10,则使用自带的即可,如果是 Windows 7 或 8.1,可以安装 PowerShell Core 6 或更新版本,安装方法见 [在 Windows 上安装 PowerShell Core](https://docs.microsoft.com/zh-cn/powershell/scripting/install/installing-powershell-core-on-windows?view=powershell-6)。 103 | 104 | 然后确保安装了 **Visual Studio 2019** 或 **Visual Studio 2019 生成工具**(如果使用 2017 版本可能需要自行修改 `CMakeSettings.json` 中的 `generator` 参数),并勾选「使用 C++ 的桌面开发」,确保安装了 **MSVC v142**、**Windows 10 SDK**、**用于 Windows 的 C++ CMake 工具** 这三个组件。其中,如果系统中已经安装了 CMake,无需再在 VS Installer 中安装,但需要确保命令已添加进 `PATH`。除此之外,vcpkg 还要求安装 VS 的**英文语言包**。 105 | 106 | > 推荐使用 VS Code 开发,只需安装 Visual Studio 2019 生成工具,不需要安装臃肿的 VS IDE。 107 | 108 | ### 下载 SDK 109 | 110 | ```ps1 111 | git clone https://github.com/richardchien/coolq-cpp-sdk.git my-awesome-app 112 | cd my-awesome-app 113 | git submodule init 114 | git submodule update 115 | ``` 116 | 117 | ### 准备构建环境 118 | 119 | ```ps1 120 | powershell .\scripts\prepare.ps1 121 | 122 | # 如果打算使用预编译的依赖,可以运行: 123 | powershell .\scripts\prepare_prebuilt.ps1 124 | 125 | # 请不要混用上面的两个脚本,只需运行一个即可 126 | ``` 127 | 128 | [`scripts/prepare.ps1`](scripts/prepare.ps1) 脚本会在当前项目目录的 `vcpkg` 子目录中安装 vcpkg,并安装所需依赖;[`scripts/prepare_prebuilt.ps1`](scripts/prepare_prebuilt.ps1) 脚本则会下载预编译的依赖库,直接解压到当前项目目录。 129 | 130 | > 如何选择?如果你只是想快速试用 demo,建议使用 prepare_prebuilt;如果你的网络环境不佳,使用 prepare 安装依赖太慢,也可以使用 prepare_prebuilt;如果你打算开发较大型的插件项目,且希望使用 vcpkg 来方便地管理依赖,可以使用 prepare。 131 | 132 | *注意,如果 PowerShell 提示不让运行脚本,需要先使用管理员权限打开 PowerShell,运行 `Set-ExecutionPolicy Unrestricted`,然后再重新运行上面的脚本;如果 vcpkg 安装依赖时出错,比较常见的问题是网络超时,请适当设置 `HTTP_PROXY` 和 `HTTPS_PROXY`,或使用预编译依赖。* 133 | 134 | ### 修改 App Id 和相关信息 135 | 136 | 修改 [`app_id.txt`](app_id.txt) 的内容为你的 App Id,例如 `com.company.my-awesome-app`,这个 App Id 的命名规范见 [appid 规范](https://docs.cqp.im/dev/v9/appid/)。 137 | 138 | 按需修改 [`app.json`](app.json) 文件中的信息,通常需要修改 `name`、`version`、`version_id`、`author`、`description`,根据实际功能可能还需要修改 `menu` 和 `auth`,具体字段含义见 [app.json](https://docs.cqp.im/dev/v9/app.json/)。请不要修改 `event` 字段,因为事件处理函数的名字已经写死在了 SDK 中。 139 | 140 | ### 编写功能 141 | 142 | 移除 [`src/demo.cpp`](src/demo.cpp) 或在其基础上修改,实现自己的功能。 143 | 144 | 具体 API 请参考 `src/demo.cpp`,或顺着 [`src/cqsdk/cqsdk.h`](src/cqsdk/cqsdk.h) 头文件找进去,IDE 的自动补全帮助会很大。除此之外,还可以参考 [richardchien/coolq-http-api](https://github.com/richardchien/coolq-http-api) 项目。 145 | 146 | **注意,所有代码文件必须使用 UTF-8 编码。如果你使用 VS,则它默认使用 ANSI 编码保存新创建的文件,需要手动修改为 UTF-8。** 147 | 148 | ### 构建项目 149 | 150 | ```ps1 151 | powershell .\scripts\generate.ps1 Debug 152 | powershell .\scripts\build.ps1 Debug 153 | ``` 154 | 155 | 上面两条命令分别生成 build 目录和构建项目,将 `Debug` 改为 `Release` 可以构建 release 版本。如果安装了 CMake 还没支持的较新版本 VS,需要先手动进入 VS 2019 的 Developer Command Prompt,再执行上面的命令。 156 | 157 | 如果你使用 VS Code,可以直接运行 task;如果使用 VS,可以直接选择菜单 CMake - 全部生成。 158 | 159 | ### 安装插件到 酷Q 160 | 161 | 首先**确保开启了 酷Q 的开发模式**,并了解 酷Q 应用开发、调试、打包的基本流程,见 [快速入门](https://docs.cqp.im/dev/v9/getting-started/)。 162 | 163 | 在项目构建完成后,复制 `build/Debug/Debug`(如果是 release 编译则是 `build/Release/Release`)中和你的 App Id 名字相同的文件夹到 酷Q 的 `dev` 目录下,在 酷Q 中重载应用即可。 164 | 165 | 如果不想每次构建后都手动安装插件,可以添加 `scripts/install.ps1` 文件(使用 UTF-16 LE 编码)如下: 166 | 167 | ```ps1 168 | $coolqRoot = "C:\Users\Richard\Lab\酷Q Pro" # 注意修改 酷Q 目录 169 | 170 | $appId = $args[0] 171 | $libName = $args[1] 172 | $appOutDir = $args[2] 173 | 174 | $coolqAppDevDir = "$coolqRoot\dev\$appId" 175 | $dllName = "$libName.dll" 176 | $dllPath = "$appOutDir\$dllName" 177 | $jsonName = "$libName.json" 178 | $jsonPath = "$appOutDir\$jsonName" 179 | 180 | Write-Host "正在拷贝插件到 酷Q 应用文件夹……" 181 | 182 | New-Item -Path $coolqAppDevDir -ItemType Directory -ErrorAction SilentlyContinue 183 | Copy-Item -Force $dllPath "$coolqAppDevDir\$dllName" 184 | Copy-Item -Force $jsonPath "$coolqAppDevDir\$jsonName" 185 | 186 | Write-Host "拷贝完成" -ForegroundColor Green 187 | ``` 188 | 189 | 后期生成事件脚本 [`scripts\post_build.ps1`](scripts\post_build.ps1) 发现存在 `scripts/install.ps1` 时会自动运行它,从而将构建出的 DLL 和 JSON 文件安装到 酷Q,此时在 酷Q 悬浮窗快速重启即可。 190 | 191 | ### 更新 SDK 192 | 193 | ```ps1 194 | git submodule update 195 | ``` 196 | 197 | 此命令会更新 `src/cqsdk` 中的 SDK 核心代码。 198 | 199 | 如果需要更新 `CMakeLists.txt`、`scripts` 等构建相关文件,使用 `git pull`,注意可能需要处理冲突。 200 | 201 | ### 安装依赖 202 | 203 | 如果需要安装依赖,可以直接使用 vcpkg(注意,前提是前面的准备步骤中安装了完整的 vcpkg,而不是预编译依赖),通过 `--triplet x86-windows-static-custom` 指定 triplet,或者使用 SDK 提供的包装脚本(参数和 vcpkg 相同),例如: 204 | 205 | ```ps1 206 | .\scripts\vcpkg.ps1 install curl 207 | ``` 208 | 209 | 然后按需在 `CMakeLists.txt` 添加相应 `find_package` 语句和修改 `target_link_libraries`。注意,vcpkg 的 CMake 工具链文件有时并不能正确找到依赖的依赖的 LIB 文件,需要手动编写 `FindXxx.cmake` 文件,参考 [`richardchien/coolq-http-api/cmake/Modules/FindCURL.cmake`](https://github.com/richardchien/coolq-http-api/blob/master/cmake/Modules/FindCURL.cmake)。 210 | 211 | ### 固定依赖包版本 212 | 213 | 对于依赖比较多的大型项目,依赖之间关系可能比较复杂,vcpkg 默认是直接安装最新版本,这会导致在部分依赖进行了不兼容的更新、而另一些依赖还没有跟进的情况下,整个项目无法编译。 214 | 215 | [Vcpkg 官方建议的做法](https://github.com/Microsoft/vcpkg/blob/master/docs/about/faq.md#how-do-i-use-different-versions-of-a-library-on-one-machine) 是,使用 Git 将 `ports` 目录固定在一切 OK 的版本,例如: 216 | 217 | ```ps1 218 | git checkout 7578a485b181ded330b87cc72726f01e38ff7ed6 -- ports 219 | ``` 220 | 221 | 为了避免每次换开发环境都要手动 checkout,可以在项目根目录添加文件 `vcpkg-commit.txt` 如下: 222 | 223 | ``` 224 | 7578a485b181ded330b87cc72726f01e38ff7ed6 225 | ``` 226 | 227 | 内容是 Git commit 的 hash。`scripts/prepare.ps1` 脚本会自动在准备构建环境的时候将 `ports` 目录固定到此 commit 的版本。 228 | 229 | ### 使用 CI 自动构建 230 | 231 | [`.appveyor.yml`](.appveyor.yml) 提供了 [AppVeyor](https://www.appveyor.com/) 的配置,几乎不用修改便可直接使用:在 AppVeyor 中新建项目,选好项目仓库,然后在 Settings 中「Custom configuration .yml file name」处填写 `.appveyor.yml` 即可。 232 | 233 | 在每次 Git 推送之后,CI 会自动运行构建脚本,并将构建出的 `app.dll` 和 `app.json` 打包进 `.zip`,可在 AppVeyor 构建任务的「Artifacts」处下载。 234 | 235 | 注意,目前无法直接打包成 CPK 格式,如需分发,仍需手动在 酷Q 应用目录中打包。 236 | 237 | ### 分发应用 238 | 239 | 如果需要向用户分发应用(打包好的 CPK),需要提示用户安装 Visual C++ 可再发行软件包,下载地址见 [最新支持的 Visual C++ 下载](https://support.microsoft.com/zh-cn/help/2977003/the-latest-supported-visual-c-downloads)。 240 | 241 | ## 插件生命周期 242 | 243 | ``` 244 | +-----------------------------------------+ 245 | | Enabled At Start | 246 | +-----------------------------------------+ 247 | | on_initialize | 248 | | + | 249 | | | | 250 | | v | 251 | | on_coolq_start | 252 | | + | 253 | | | | 254 | | v disabled by user | 255 | | on_enable +--------------> on_disable | 256 | | + + | 257 | | | | | 258 | | v | | 259 | | on_coolq_exit <-------------------+ | 260 | +-----------------------------------------+ 261 | 262 | +---------------------------------------+ 263 | | Disabled At Start | 264 | +---------------------------------------+ 265 | | on_initialize +------+ | 266 | | + |enabled by user | 267 | | | | | 268 | | | v | 269 | | | on_coolq_start | 270 | | | + | 271 | | | | | 272 | | | v | 273 | | | on_enable | 274 | | | + | 275 | | | | | 276 | | v | | 277 | | on_coolq_exit <------+ | 278 | +---------------------------------------+ 279 | ``` 280 | 281 | ## 应用案例 282 | 283 | | 项目地址 | 简介 | 284 | | --------------------------------------------------------------------------------- | -------------------------------- | 285 | | [richardchien/coolq-http-api](https://github.com/richardchien/coolq-http-api) | 酷Q HTTP API 插件 | 286 | | [JogleLew/coolq-telegram-bot-x](https://github.com/JogleLew/coolq-telegram-bot-x) | QQ / Telegram 群组消息转发机器人 | 287 | | [dynilath/coolq-dicebot](https://github.com/dynilath/coolq-dicebot) | 酷Q 骰子机器人 | 288 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "ret": 1, 3 | "apiver": 9, 4 | "name": "Demo", 5 | "version": "1.0.0", 6 | "version_id": 1, 7 | "author": "Your Name", 8 | "description": "这是 CoolQ C++ SDK 的一个 Demo。", 9 | "event": [ 10 | { 11 | "id": 1003, 12 | "type": 1003, 13 | "name": "插件启用", 14 | "priority": 30000, 15 | "function": "cq_app_enable" 16 | }, 17 | { 18 | "id": 1004, 19 | "type": 1004, 20 | "name": "插件停用", 21 | "priority": 30000, 22 | "function": "cq_app_disable" 23 | }, 24 | { 25 | "id": 1001, 26 | "type": 1001, 27 | "name": "酷Q启动", 28 | "priority": 30000, 29 | "function": "cq_coolq_start" 30 | }, 31 | { 32 | "id": 1002, 33 | "type": 1002, 34 | "name": "酷Q退出", 35 | "priority": 30000, 36 | "function": "cq_coolq_exit" 37 | }, 38 | { 39 | "id": 1, 40 | "type": 21, 41 | "name": "私聊消息", 42 | "function": "cq_event_private_msg", 43 | "priority": 30000 44 | }, 45 | { 46 | "id": 2, 47 | "type": 2, 48 | "name": "群消息", 49 | "function": "cq_event_group_msg", 50 | "priority": 30000 51 | }, 52 | { 53 | "id": 3, 54 | "type": 4, 55 | "name": "讨论组消息", 56 | "function": "cq_event_discuss_msg", 57 | "priority": 30000 58 | }, 59 | { 60 | "id": 4, 61 | "type": 11, 62 | "name": "群文件上传", 63 | "function": "cq_event_group_upload", 64 | "priority": 30000 65 | }, 66 | { 67 | "id": 5, 68 | "type": 101, 69 | "name": "群管理员变动", 70 | "function": "cq_event_group_admin", 71 | "priority": 30000 72 | }, 73 | { 74 | "id": 6, 75 | "type": 102, 76 | "name": "群成员减少", 77 | "function": "cq_event_group_member_decrease", 78 | "priority": 30000 79 | }, 80 | { 81 | "id": 7, 82 | "type": 103, 83 | "name": "群成员增加", 84 | "function": "cq_event_group_member_increase", 85 | "priority": 30000 86 | }, 87 | { 88 | "id": 8, 89 | "type": 104, 90 | "name": "群禁言", 91 | "function": "cq_event_group_ban", 92 | "priority": 30000 93 | }, 94 | { 95 | "id": 10, 96 | "type": 201, 97 | "name": "好友添加", 98 | "function": "cq_event_friend_add", 99 | "priority": 30000 100 | }, 101 | { 102 | "id": 11, 103 | "type": 301, 104 | "name": "加好友请求", 105 | "function": "cq_event_add_friend_request", 106 | "priority": 30000 107 | }, 108 | { 109 | "id": 12, 110 | "type": 302, 111 | "name": "加群请求/邀请", 112 | "function": "cq_event_add_group_request", 113 | "priority": 30000 114 | } 115 | ], 116 | "menu": [ 117 | { 118 | "name": "菜单 1", 119 | "function": "menu_demo_1" 120 | }, 121 | { 122 | "name": "菜单 2", 123 | "function": "menu_demo_2" 124 | } 125 | ], 126 | "status": [], 127 | "auth": [ 128 | // 20, // getCookies / getCsrfToken 129 | // 30, // getRecord 130 | 101, // sendGroupMsg 131 | 103, // sendDiscussMsg 132 | 106, // sendPrivateMsg 133 | // 110, // sendLikeV2 / sendLike 134 | // 120, // setGroupKick 135 | // 121, // setGroupBan 136 | // 122, // setGroupAdmin 137 | // 123, // setGroupWholeBan 138 | // 124, // setGroupAnonymousBan 139 | // 125, // setGroupAnonymous 140 | // 126, // setGroupCard 141 | // 127, // setGroupLeave 142 | // 128, // setGroupSpecialTitle 143 | 130, // getGroupMemberInfoV2 / getGroupMemberInfo 144 | 131, // getStrangerInfo 145 | 132, // getGroupInfo 146 | // 140, // setDiscussLeave 147 | // 150, // setFriendAddRequest 148 | // 151, // setGroupAddRequest 149 | 160, // getGroupMemberList 150 | 161, // getGroupList 151 | 162, // getFriendList 152 | 180 // deleteMsg 153 | ] 154 | } -------------------------------------------------------------------------------- /app_id.txt: -------------------------------------------------------------------------------- 1 | com.example.demo -------------------------------------------------------------------------------- /cmake/Modules/FindVcpkgIncludeDir.cmake: -------------------------------------------------------------------------------- 1 | find_path(VCPKG_INCLUDE_DIR iconv.h) 2 | -------------------------------------------------------------------------------- /cmake/Modules/FixDebugLibraryLookup.cmake: -------------------------------------------------------------------------------- 1 | if(CMAKE_BUILD_TYPE MATCHES "^Debug$") 2 | # fix Vcpkg debug library lookup bug, see https://github.com/Microsoft/vcpkg/issues/1626 3 | list(APPEND CMAKE_IGNORE_PATH ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib) 4 | endif() 5 | -------------------------------------------------------------------------------- /cmake/Modules/FixLinkConflict.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCD /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:MSVCRT") 2 | set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCD /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:MSVCRTD") 3 | -------------------------------------------------------------------------------- /cmake/Modules/cotire.cmake: -------------------------------------------------------------------------------- 1 | # - cotire (compile time reducer) 2 | # 3 | # See the cotire manual for usage hints. 4 | # 5 | #============================================================================= 6 | # Copyright 2012-2018 Sascha Kratky 7 | # 8 | # Permission is hereby granted, free of charge, to any person 9 | # obtaining a copy of this software and associated documentation 10 | # files (the "Software"), to deal in the Software without 11 | # restriction, including without limitation the rights to use, 12 | # copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the 14 | # Software is furnished to do so, subject to the following 15 | # conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be 18 | # included in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | # OTHER DEALINGS IN THE SOFTWARE. 28 | #============================================================================= 29 | 30 | if(__COTIRE_INCLUDED) 31 | return() 32 | endif() 33 | set(__COTIRE_INCLUDED TRUE) 34 | 35 | # call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode 36 | # cmake_minimum_required also sets the policy version as a side effect, which we have to avoid 37 | if (NOT CMAKE_SCRIPT_MODE_FILE) 38 | cmake_policy(PUSH) 39 | endif() 40 | cmake_minimum_required(VERSION 2.8.12) 41 | if (NOT CMAKE_SCRIPT_MODE_FILE) 42 | cmake_policy(POP) 43 | endif() 44 | 45 | set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") 46 | set (COTIRE_CMAKE_MODULE_VERSION "1.8.0") 47 | 48 | # activate select policies 49 | if (POLICY CMP0025) 50 | # Compiler id for Apple Clang is now AppleClang 51 | cmake_policy(SET CMP0025 NEW) 52 | endif() 53 | 54 | if (POLICY CMP0026) 55 | # disallow use of the LOCATION target property 56 | cmake_policy(SET CMP0026 NEW) 57 | endif() 58 | 59 | if (POLICY CMP0038) 60 | # targets may not link directly to themselves 61 | cmake_policy(SET CMP0038 NEW) 62 | endif() 63 | 64 | if (POLICY CMP0039) 65 | # utility targets may not have link dependencies 66 | cmake_policy(SET CMP0039 NEW) 67 | endif() 68 | 69 | if (POLICY CMP0040) 70 | # target in the TARGET signature of add_custom_command() must exist 71 | cmake_policy(SET CMP0040 NEW) 72 | endif() 73 | 74 | if (POLICY CMP0045) 75 | # error on non-existent target in get_target_property 76 | cmake_policy(SET CMP0045 NEW) 77 | endif() 78 | 79 | if (POLICY CMP0046) 80 | # error on non-existent dependency in add_dependencies 81 | cmake_policy(SET CMP0046 NEW) 82 | endif() 83 | 84 | if (POLICY CMP0049) 85 | # do not expand variables in target source entries 86 | cmake_policy(SET CMP0049 NEW) 87 | endif() 88 | 89 | if (POLICY CMP0050) 90 | # disallow add_custom_command SOURCE signatures 91 | cmake_policy(SET CMP0050 NEW) 92 | endif() 93 | 94 | if (POLICY CMP0051) 95 | # include TARGET_OBJECTS expressions in a target's SOURCES property 96 | cmake_policy(SET CMP0051 NEW) 97 | endif() 98 | 99 | if (POLICY CMP0053) 100 | # simplify variable reference and escape sequence evaluation 101 | cmake_policy(SET CMP0053 NEW) 102 | endif() 103 | 104 | if (POLICY CMP0054) 105 | # only interpret if() arguments as variables or keywords when unquoted 106 | cmake_policy(SET CMP0054 NEW) 107 | endif() 108 | 109 | if (POLICY CMP0055) 110 | # strict checking for break() command 111 | cmake_policy(SET CMP0055 NEW) 112 | endif() 113 | 114 | include(CMakeParseArguments) 115 | include(ProcessorCount) 116 | 117 | function (cotire_get_configuration_types _configsVar) 118 | set (_configs "") 119 | if (CMAKE_CONFIGURATION_TYPES) 120 | list (APPEND _configs ${CMAKE_CONFIGURATION_TYPES}) 121 | endif() 122 | if (CMAKE_BUILD_TYPE) 123 | list (APPEND _configs "${CMAKE_BUILD_TYPE}") 124 | endif() 125 | if (_configs) 126 | list (REMOVE_DUPLICATES _configs) 127 | set (${_configsVar} ${_configs} PARENT_SCOPE) 128 | else() 129 | set (${_configsVar} "None" PARENT_SCOPE) 130 | endif() 131 | endfunction() 132 | 133 | function (cotire_get_source_file_extension _sourceFile _extVar) 134 | # get_filename_component returns extension from first occurrence of . in file name 135 | # this function computes the extension from last occurrence of . in file name 136 | string (FIND "${_sourceFile}" "." _index REVERSE) 137 | if (_index GREATER -1) 138 | math (EXPR _index "${_index} + 1") 139 | string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) 140 | else() 141 | set (_sourceExt "") 142 | endif() 143 | set (${_extVar} "${_sourceExt}" PARENT_SCOPE) 144 | endfunction() 145 | 146 | macro (cotire_check_is_path_relative_to _path _isRelativeVar) 147 | set (${_isRelativeVar} FALSE) 148 | if (IS_ABSOLUTE "${_path}") 149 | foreach (_dir ${ARGN}) 150 | file (RELATIVE_PATH _relPath "${_dir}" "${_path}") 151 | if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) 152 | set (${_isRelativeVar} TRUE) 153 | break() 154 | endif() 155 | endforeach() 156 | endif() 157 | endmacro() 158 | 159 | function (cotire_filter_language_source_files _language _target _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) 160 | if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) 161 | set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") 162 | else() 163 | set (_languageExtensions "") 164 | endif() 165 | if (CMAKE_${_language}_IGNORE_EXTENSIONS) 166 | set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") 167 | else() 168 | set (_ignoreExtensions "") 169 | endif() 170 | if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS) 171 | set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}") 172 | else() 173 | set (_excludeExtensions "") 174 | endif() 175 | if (COTIRE_DEBUG AND _languageExtensions) 176 | message (STATUS "${_language} source file extensions: ${_languageExtensions}") 177 | endif() 178 | if (COTIRE_DEBUG AND _ignoreExtensions) 179 | message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") 180 | endif() 181 | if (COTIRE_DEBUG AND _excludeExtensions) 182 | message (STATUS "${_language} exclude extensions: ${_excludeExtensions}") 183 | endif() 184 | if (CMAKE_VERSION VERSION_LESS "3.1.0") 185 | set (_allSourceFiles ${ARGN}) 186 | else() 187 | # as of CMake 3.1 target sources may contain generator expressions 188 | # since we cannot obtain required property information about source files added 189 | # through generator expressions at configure time, we filter them out 190 | string (GENEX_STRIP "${ARGN}" _allSourceFiles) 191 | endif() 192 | set (_filteredSourceFiles "") 193 | set (_excludedSourceFiles "") 194 | foreach (_sourceFile ${_allSourceFiles}) 195 | get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) 196 | get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) 197 | get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) 198 | if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) 199 | cotire_get_source_file_extension("${_sourceFile}" _sourceExt) 200 | if (_sourceExt) 201 | list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) 202 | if (_ignoreIndex LESS 0) 203 | list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex) 204 | if (_excludeIndex GREATER -1) 205 | list (APPEND _excludedSourceFiles "${_sourceFile}") 206 | else() 207 | list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) 208 | if (_sourceIndex GREATER -1) 209 | # consider source file unless it is excluded explicitly 210 | get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) 211 | if (_sourceIsExcluded) 212 | list (APPEND _excludedSourceFiles "${_sourceFile}") 213 | else() 214 | list (APPEND _filteredSourceFiles "${_sourceFile}") 215 | endif() 216 | else() 217 | get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) 218 | if ("${_sourceLanguage}" STREQUAL "${_language}") 219 | # add to excluded sources, if file is not ignored and has correct language without having the correct extension 220 | list (APPEND _excludedSourceFiles "${_sourceFile}") 221 | endif() 222 | endif() 223 | endif() 224 | endif() 225 | endif() 226 | endif() 227 | endforeach() 228 | # separate filtered source files from already cotired ones 229 | # the COTIRE_TARGET property of a source file may be set while a target is being processed by cotire 230 | set (_sourceFiles "") 231 | set (_cotiredSourceFiles "") 232 | foreach (_sourceFile ${_filteredSourceFiles}) 233 | get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) 234 | if (_sourceIsCotired) 235 | list (APPEND _cotiredSourceFiles "${_sourceFile}") 236 | else() 237 | get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) 238 | if (_sourceCompileFlags) 239 | # add to excluded sources, if file has custom compile flags 240 | list (APPEND _excludedSourceFiles "${_sourceFile}") 241 | else() 242 | get_source_file_property(_sourceCompileOptions "${_sourceFile}" COMPILE_OPTIONS) 243 | if (_sourceCompileOptions) 244 | # add to excluded sources, if file has list of custom compile options 245 | list (APPEND _excludedSourceFiles "${_sourceFile}") 246 | else() 247 | list (APPEND _sourceFiles "${_sourceFile}") 248 | endif() 249 | endif() 250 | endif() 251 | endforeach() 252 | if (COTIRE_DEBUG) 253 | if (_sourceFiles) 254 | message (STATUS "Filtered ${_target} ${_language} sources: ${_sourceFiles}") 255 | endif() 256 | if (_excludedSourceFiles) 257 | message (STATUS "Excluded ${_target} ${_language} sources: ${_excludedSourceFiles}") 258 | endif() 259 | if (_cotiredSourceFiles) 260 | message (STATUS "Cotired ${_target} ${_language} sources: ${_cotiredSourceFiles}") 261 | endif() 262 | endif() 263 | set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) 264 | set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) 265 | set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) 266 | endfunction() 267 | 268 | function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) 269 | set (_filteredObjects "") 270 | foreach (_object ${ARGN}) 271 | get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) 272 | if (_isSet) 273 | get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) 274 | if (_propertyValue) 275 | list (APPEND _filteredObjects "${_object}") 276 | endif() 277 | endif() 278 | endforeach() 279 | set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) 280 | endfunction() 281 | 282 | function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) 283 | set (_filteredObjects "") 284 | foreach (_object ${ARGN}) 285 | get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) 286 | if (_isSet) 287 | get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) 288 | if (NOT _propertyValue) 289 | list (APPEND _filteredObjects "${_object}") 290 | endif() 291 | endif() 292 | endforeach() 293 | set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) 294 | endfunction() 295 | 296 | function (cotire_get_source_file_property_values _valuesVar _property) 297 | set (_values "") 298 | foreach (_sourceFile ${ARGN}) 299 | get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) 300 | if (_propertyValue) 301 | list (APPEND _values "${_propertyValue}") 302 | endif() 303 | endforeach() 304 | set (${_valuesVar} ${_values} PARENT_SCOPE) 305 | endfunction() 306 | 307 | function (cotire_resolve_config_properties _configurations _propertiesVar) 308 | set (_properties "") 309 | foreach (_property ${ARGN}) 310 | if ("${_property}" MATCHES "") 311 | foreach (_config ${_configurations}) 312 | string (TOUPPER "${_config}" _upperConfig) 313 | string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") 314 | list (APPEND _properties ${_configProperty}) 315 | endforeach() 316 | else() 317 | list (APPEND _properties ${_property}) 318 | endif() 319 | endforeach() 320 | set (${_propertiesVar} ${_properties} PARENT_SCOPE) 321 | endfunction() 322 | 323 | function (cotire_copy_set_properties _configurations _type _source _target) 324 | cotire_resolve_config_properties("${_configurations}" _properties ${ARGN}) 325 | foreach (_property ${_properties}) 326 | get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) 327 | if (_isSet) 328 | get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) 329 | set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") 330 | endif() 331 | endforeach() 332 | endfunction() 333 | 334 | function (cotire_get_target_usage_requirements _target _config _targetRequirementsVar) 335 | set (_targetRequirements "") 336 | get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES) 337 | while (_librariesToProcess) 338 | # remove from head 339 | list (GET _librariesToProcess 0 _library) 340 | list (REMOVE_AT _librariesToProcess 0) 341 | if (_library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") 342 | set (_library "${CMAKE_MATCH_1}") 343 | elseif (_config STREQUAL "None" AND _library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") 344 | set (_library "${CMAKE_MATCH_1}") 345 | endif() 346 | if (TARGET ${_library}) 347 | list (FIND _targetRequirements ${_library} _index) 348 | if (_index LESS 0) 349 | list (APPEND _targetRequirements ${_library}) 350 | # BFS traversal of transitive libraries 351 | get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES) 352 | if (_libraries) 353 | list (APPEND _librariesToProcess ${_libraries}) 354 | list (REMOVE_DUPLICATES _librariesToProcess) 355 | endif() 356 | endif() 357 | endif() 358 | endwhile() 359 | set (${_targetRequirementsVar} ${_targetRequirements} PARENT_SCOPE) 360 | endfunction() 361 | 362 | function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar) 363 | if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") 364 | set (_flagPrefix "[/-]") 365 | else() 366 | set (_flagPrefix "--?") 367 | endif() 368 | set (_optionFlag "") 369 | set (_matchedOptions "") 370 | set (_unmatchedOptions "") 371 | foreach (_compileFlag ${ARGN}) 372 | if (_compileFlag) 373 | if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") 374 | # option with separate argument 375 | list (APPEND _matchedOptions "${_compileFlag}") 376 | set (_optionFlag "") 377 | elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") 378 | # remember option 379 | set (_optionFlag "${CMAKE_MATCH_2}") 380 | elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") 381 | # option with joined argument 382 | list (APPEND _matchedOptions "${CMAKE_MATCH_3}") 383 | set (_optionFlag "") 384 | else() 385 | # flush remembered option 386 | if (_optionFlag) 387 | list (APPEND _matchedOptions "${_optionFlag}") 388 | set (_optionFlag "") 389 | endif() 390 | # add to unfiltered options 391 | list (APPEND _unmatchedOptions "${_compileFlag}") 392 | endif() 393 | endif() 394 | endforeach() 395 | if (_optionFlag) 396 | list (APPEND _matchedOptions "${_optionFlag}") 397 | endif() 398 | if (COTIRE_DEBUG AND _matchedOptions) 399 | message (STATUS "Filter ${_flagFilter} matched: ${_matchedOptions}") 400 | endif() 401 | if (COTIRE_DEBUG AND _unmatchedOptions) 402 | message (STATUS "Filter ${_flagFilter} unmatched: ${_unmatchedOptions}") 403 | endif() 404 | set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) 405 | set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) 406 | endfunction() 407 | 408 | function (cotire_is_target_supported _target _isSupportedVar) 409 | if (NOT TARGET "${_target}") 410 | set (${_isSupportedVar} FALSE PARENT_SCOPE) 411 | return() 412 | endif() 413 | get_target_property(_imported ${_target} IMPORTED) 414 | if (_imported) 415 | set (${_isSupportedVar} FALSE PARENT_SCOPE) 416 | return() 417 | endif() 418 | get_target_property(_targetType ${_target} TYPE) 419 | if (NOT _targetType MATCHES "EXECUTABLE|(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") 420 | set (${_isSupportedVar} FALSE PARENT_SCOPE) 421 | return() 422 | endif() 423 | set (${_isSupportedVar} TRUE PARENT_SCOPE) 424 | endfunction() 425 | 426 | function (cotire_get_target_compile_flags _config _language _target _flagsVar) 427 | string (TOUPPER "${_config}" _upperConfig) 428 | # collect options from CMake language variables 429 | set (_compileFlags "") 430 | if (CMAKE_${_language}_FLAGS) 431 | set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") 432 | endif() 433 | if (CMAKE_${_language}_FLAGS_${_upperConfig}) 434 | set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") 435 | endif() 436 | if (_target) 437 | # add target compile flags 438 | get_target_property(_targetflags ${_target} COMPILE_FLAGS) 439 | if (_targetflags) 440 | set (_compileFlags "${_compileFlags} ${_targetflags}") 441 | endif() 442 | endif() 443 | if (UNIX) 444 | separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") 445 | elseif(WIN32) 446 | separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") 447 | else() 448 | separate_arguments(_compileFlags) 449 | endif() 450 | # target compile options 451 | if (_target) 452 | get_target_property(_targetOptions ${_target} COMPILE_OPTIONS) 453 | if (_targetOptions) 454 | list (APPEND _compileFlags ${_targetOptions}) 455 | endif() 456 | endif() 457 | # interface compile options from linked library targets 458 | if (_target) 459 | set (_linkedTargets "") 460 | cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) 461 | foreach (_linkedTarget ${_linkedTargets}) 462 | get_target_property(_targetOptions ${_linkedTarget} INTERFACE_COMPILE_OPTIONS) 463 | if (_targetOptions) 464 | list (APPEND _compileFlags ${_targetOptions}) 465 | endif() 466 | endforeach() 467 | endif() 468 | # handle language standard properties 469 | if (CMAKE_${_language}_STANDARD_DEFAULT) 470 | # used compiler supports language standard levels 471 | if (_target) 472 | get_target_property(_targetLanguageStandard ${_target} ${_language}_STANDARD) 473 | if (_targetLanguageStandard) 474 | set (_type "EXTENSION") 475 | get_property(_isSet TARGET ${_target} PROPERTY ${_language}_EXTENSIONS SET) 476 | if (_isSet) 477 | get_target_property(_targetUseLanguageExtensions ${_target} ${_language}_EXTENSIONS) 478 | if (NOT _targetUseLanguageExtensions) 479 | set (_type "STANDARD") 480 | endif() 481 | endif() 482 | if (CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION) 483 | list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION}") 484 | endif() 485 | endif() 486 | endif() 487 | endif() 488 | # handle the POSITION_INDEPENDENT_CODE target property 489 | if (_target) 490 | get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE) 491 | if (_targetPIC) 492 | get_target_property(_targetType ${_target} TYPE) 493 | if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE) 494 | list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIE}") 495 | elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC) 496 | list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIC}") 497 | endif() 498 | endif() 499 | endif() 500 | # handle visibility target properties 501 | if (_target) 502 | get_target_property(_targetVisibility ${_target} ${_language}_VISIBILITY_PRESET) 503 | if (_targetVisibility AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY) 504 | list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY}${_targetVisibility}") 505 | endif() 506 | get_target_property(_targetVisibilityInlines ${_target} VISIBILITY_INLINES_HIDDEN) 507 | if (_targetVisibilityInlines AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN) 508 | list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN}") 509 | endif() 510 | endif() 511 | # platform specific flags 512 | if (APPLE) 513 | get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) 514 | if (NOT _architectures) 515 | get_target_property(_architectures ${_target} OSX_ARCHITECTURES) 516 | endif() 517 | if (_architectures) 518 | foreach (_arch ${_architectures}) 519 | list (APPEND _compileFlags "-arch" "${_arch}") 520 | endforeach() 521 | endif() 522 | if (CMAKE_OSX_SYSROOT) 523 | if (CMAKE_${_language}_SYSROOT_FLAG) 524 | list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}") 525 | else() 526 | list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") 527 | endif() 528 | endif() 529 | if (CMAKE_OSX_DEPLOYMENT_TARGET) 530 | if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) 531 | list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") 532 | else() 533 | list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") 534 | endif() 535 | endif() 536 | endif() 537 | if (COTIRE_DEBUG AND _compileFlags) 538 | message (STATUS "Target ${_target} compile flags: ${_compileFlags}") 539 | endif() 540 | set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) 541 | endfunction() 542 | 543 | function (cotire_get_target_include_directories _config _language _target _includeDirsVar _systemIncludeDirsVar) 544 | set (_includeDirs "") 545 | set (_systemIncludeDirs "") 546 | # default include dirs 547 | if (CMAKE_INCLUDE_CURRENT_DIR) 548 | list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}") 549 | list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}") 550 | endif() 551 | set (_targetFlags "") 552 | cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) 553 | # parse additional include directories from target compile flags 554 | if (CMAKE_INCLUDE_FLAG_${_language}) 555 | string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) 556 | string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") 557 | if (_includeFlag) 558 | set (_dirs "") 559 | cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) 560 | if (_dirs) 561 | list (APPEND _includeDirs ${_dirs}) 562 | endif() 563 | endif() 564 | endif() 565 | # parse additional system include directories from target compile flags 566 | if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) 567 | string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) 568 | string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") 569 | if (_includeFlag) 570 | set (_dirs "") 571 | cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) 572 | if (_dirs) 573 | list (APPEND _systemIncludeDirs ${_dirs}) 574 | endif() 575 | endif() 576 | endif() 577 | # target include directories 578 | get_directory_property(_dirs DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" INCLUDE_DIRECTORIES) 579 | if (_target) 580 | get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) 581 | if (_targetDirs) 582 | list (APPEND _dirs ${_targetDirs}) 583 | endif() 584 | get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) 585 | if (_targetDirs) 586 | list (APPEND _systemIncludeDirs ${_targetDirs}) 587 | endif() 588 | endif() 589 | # interface include directories from linked library targets 590 | if (_target) 591 | set (_linkedTargets "") 592 | cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) 593 | foreach (_linkedTarget ${_linkedTargets}) 594 | get_target_property(_linkedTargetType ${_linkedTarget} TYPE) 595 | if (CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE AND NOT CMAKE_VERSION VERSION_LESS "3.4.0" AND 596 | _linkedTargetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") 597 | # CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE refers to CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR 598 | # at the time, when the target was created. These correspond to the target properties BINARY_DIR and SOURCE_DIR 599 | # which are only available with CMake 3.4 or later. 600 | get_target_property(_targetDirs ${_linkedTarget} BINARY_DIR) 601 | if (_targetDirs) 602 | list (APPEND _dirs ${_targetDirs}) 603 | endif() 604 | get_target_property(_targetDirs ${_linkedTarget} SOURCE_DIR) 605 | if (_targetDirs) 606 | list (APPEND _dirs ${_targetDirs}) 607 | endif() 608 | endif() 609 | get_target_property(_targetDirs ${_linkedTarget} INTERFACE_INCLUDE_DIRECTORIES) 610 | if (_targetDirs) 611 | list (APPEND _dirs ${_targetDirs}) 612 | endif() 613 | get_target_property(_targetDirs ${_linkedTarget} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) 614 | if (_targetDirs) 615 | list (APPEND _systemIncludeDirs ${_targetDirs}) 616 | endif() 617 | endforeach() 618 | endif() 619 | if (dirs) 620 | list (REMOVE_DUPLICATES _dirs) 621 | endif() 622 | list (LENGTH _includeDirs _projectInsertIndex) 623 | foreach (_dir ${_dirs}) 624 | if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) 625 | cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") 626 | if (_isRelative) 627 | list (LENGTH _includeDirs _len) 628 | if (_len EQUAL _projectInsertIndex) 629 | list (APPEND _includeDirs "${_dir}") 630 | else() 631 | list (INSERT _includeDirs _projectInsertIndex "${_dir}") 632 | endif() 633 | math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") 634 | else() 635 | list (APPEND _includeDirs "${_dir}") 636 | endif() 637 | else() 638 | list (APPEND _includeDirs "${_dir}") 639 | endif() 640 | endforeach() 641 | list (REMOVE_DUPLICATES _includeDirs) 642 | list (REMOVE_DUPLICATES _systemIncludeDirs) 643 | if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) 644 | list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) 645 | endif() 646 | if (WIN32 AND NOT MINGW) 647 | # convert Windows paths in include directories to CMake paths 648 | if (_includeDirs) 649 | set (_paths "") 650 | foreach (_dir ${_includeDirs}) 651 | file (TO_CMAKE_PATH "${_dir}" _path) 652 | list (APPEND _paths "${_path}") 653 | endforeach() 654 | set (_includeDirs ${_paths}) 655 | endif() 656 | if (_systemIncludeDirs) 657 | set (_paths "") 658 | foreach (_dir ${_systemIncludeDirs}) 659 | file (TO_CMAKE_PATH "${_dir}" _path) 660 | list (APPEND _paths "${_path}") 661 | endforeach() 662 | set (_systemIncludeDirs ${_paths}) 663 | endif() 664 | endif() 665 | if (COTIRE_DEBUG AND _includeDirs) 666 | message (STATUS "Target ${_target} include dirs: ${_includeDirs}") 667 | endif() 668 | set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) 669 | if (COTIRE_DEBUG AND _systemIncludeDirs) 670 | message (STATUS "Target ${_target} system include dirs: ${_systemIncludeDirs}") 671 | endif() 672 | set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE) 673 | endfunction() 674 | 675 | function (cotire_get_target_export_symbol _target _exportSymbolVar) 676 | set (_exportSymbol "") 677 | get_target_property(_targetType ${_target} TYPE) 678 | get_target_property(_enableExports ${_target} ENABLE_EXPORTS) 679 | if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR 680 | (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) 681 | get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) 682 | if (NOT _exportSymbol) 683 | set (_exportSymbol "${_target}_EXPORTS") 684 | endif() 685 | string (MAKE_C_IDENTIFIER "${_exportSymbol}" _exportSymbol) 686 | endif() 687 | set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) 688 | endfunction() 689 | 690 | function (cotire_get_target_compile_definitions _config _language _target _definitionsVar) 691 | string (TOUPPER "${_config}" _upperConfig) 692 | set (_configDefinitions "") 693 | # CMAKE_INTDIR for multi-configuration build systems 694 | if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") 695 | list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") 696 | endif() 697 | # target export define symbol 698 | cotire_get_target_export_symbol("${_target}" _defineSymbol) 699 | if (_defineSymbol) 700 | list (APPEND _configDefinitions "${_defineSymbol}") 701 | endif() 702 | # directory compile definitions 703 | get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS) 704 | if (_definitions) 705 | list (APPEND _configDefinitions ${_definitions}) 706 | endif() 707 | get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS_${_upperConfig}) 708 | if (_definitions) 709 | list (APPEND _configDefinitions ${_definitions}) 710 | endif() 711 | # target compile definitions 712 | get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) 713 | if (_definitions) 714 | list (APPEND _configDefinitions ${_definitions}) 715 | endif() 716 | get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) 717 | if (_definitions) 718 | list (APPEND _configDefinitions ${_definitions}) 719 | endif() 720 | # interface compile definitions from linked library targets 721 | set (_linkedTargets "") 722 | cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) 723 | foreach (_linkedTarget ${_linkedTargets}) 724 | get_target_property(_definitions ${_linkedTarget} INTERFACE_COMPILE_DEFINITIONS) 725 | if (_definitions) 726 | list (APPEND _configDefinitions ${_definitions}) 727 | endif() 728 | endforeach() 729 | # parse additional compile definitions from target compile flags 730 | # and do not look at directory compile definitions, which we already handled 731 | set (_targetFlags "") 732 | cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) 733 | cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags}) 734 | if (_definitions) 735 | list (APPEND _configDefinitions ${_definitions}) 736 | endif() 737 | list (REMOVE_DUPLICATES _configDefinitions) 738 | if (COTIRE_DEBUG AND _configDefinitions) 739 | message (STATUS "Target ${_target} compile definitions: ${_configDefinitions}") 740 | endif() 741 | set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) 742 | endfunction() 743 | 744 | function (cotire_get_target_compiler_flags _config _language _target _compilerFlagsVar) 745 | # parse target compile flags omitting compile definitions and include directives 746 | set (_targetFlags "") 747 | cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) 748 | set (_flagFilter "D") 749 | if (CMAKE_INCLUDE_FLAG_${_language}) 750 | string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) 751 | string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") 752 | if (_includeFlag) 753 | set (_flagFilter "${_flagFilter}|${_includeFlag}") 754 | endif() 755 | endif() 756 | if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) 757 | string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) 758 | string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") 759 | if (_includeFlag) 760 | set (_flagFilter "${_flagFilter}|${_includeFlag}") 761 | endif() 762 | endif() 763 | set (_compilerFlags "") 764 | cotire_filter_compile_flags("${_language}" "${_flagFilter}" _ignore _compilerFlags ${_targetFlags}) 765 | if (COTIRE_DEBUG AND _compilerFlags) 766 | message (STATUS "Target ${_target} compiler flags: ${_compilerFlags}") 767 | endif() 768 | set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) 769 | endfunction() 770 | 771 | function (cotire_add_sys_root_paths _pathsVar) 772 | if (APPLE) 773 | if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) 774 | foreach (_path IN LISTS ${_pathsVar}) 775 | if (IS_ABSOLUTE "${_path}") 776 | get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) 777 | if (EXISTS "${_path}") 778 | list (APPEND ${_pathsVar} "${_path}") 779 | endif() 780 | endif() 781 | endforeach() 782 | endif() 783 | endif() 784 | set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) 785 | endfunction() 786 | 787 | function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) 788 | set (_extraProperties ${ARGN}) 789 | set (_result "") 790 | if (_extraProperties) 791 | list (FIND _extraProperties "${_sourceFile}" _index) 792 | if (_index GREATER -1) 793 | math (EXPR _index "${_index} + 1") 794 | list (LENGTH _extraProperties _len) 795 | math (EXPR _len "${_len} - 1") 796 | foreach (_index RANGE ${_index} ${_len}) 797 | list (GET _extraProperties ${_index} _value) 798 | if (_value MATCHES "${_pattern}") 799 | list (APPEND _result "${_value}") 800 | else() 801 | break() 802 | endif() 803 | endforeach() 804 | endif() 805 | endif() 806 | set (${_resultVar} ${_result} PARENT_SCOPE) 807 | endfunction() 808 | 809 | function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) 810 | set (_compileDefinitions "") 811 | if (NOT CMAKE_SCRIPT_MODE_FILE) 812 | string (TOUPPER "${_config}" _upperConfig) 813 | get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) 814 | if (_definitions) 815 | list (APPEND _compileDefinitions ${_definitions}) 816 | endif() 817 | get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) 818 | if (_definitions) 819 | list (APPEND _compileDefinitions ${_definitions}) 820 | endif() 821 | endif() 822 | cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) 823 | if (_definitions) 824 | list (APPEND _compileDefinitions ${_definitions}) 825 | endif() 826 | if (COTIRE_DEBUG AND _compileDefinitions) 827 | message (STATUS "Source ${_sourceFile} compile definitions: ${_compileDefinitions}") 828 | endif() 829 | set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) 830 | endfunction() 831 | 832 | function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) 833 | set (_configDefinitions "") 834 | foreach (_sourceFile ${ARGN}) 835 | cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) 836 | if (_sourceDefinitions) 837 | list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") 838 | endif() 839 | endforeach() 840 | set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) 841 | endfunction() 842 | 843 | function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) 844 | set (_sourceUndefs "") 845 | if (NOT CMAKE_SCRIPT_MODE_FILE) 846 | get_source_file_property(_undefs "${_sourceFile}" ${_property}) 847 | if (_undefs) 848 | list (APPEND _sourceUndefs ${_undefs}) 849 | endif() 850 | endif() 851 | cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) 852 | if (_undefs) 853 | list (APPEND _sourceUndefs ${_undefs}) 854 | endif() 855 | if (COTIRE_DEBUG AND _sourceUndefs) 856 | message (STATUS "Source ${_sourceFile} ${_property} undefs: ${_sourceUndefs}") 857 | endif() 858 | set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) 859 | endfunction() 860 | 861 | function (cotire_get_source_files_undefs _property _sourceUndefsVar) 862 | set (_sourceUndefs "") 863 | foreach (_sourceFile ${ARGN}) 864 | cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) 865 | if (_undefs) 866 | list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") 867 | endif() 868 | endforeach() 869 | set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) 870 | endfunction() 871 | 872 | macro (cotire_set_cmd_to_prologue _cmdVar) 873 | set (${_cmdVar} "${CMAKE_COMMAND}") 874 | if (COTIRE_DEBUG) 875 | list (APPEND ${_cmdVar} "--warn-uninitialized") 876 | endif() 877 | list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") 878 | if (XCODE) 879 | list (APPEND ${_cmdVar} "-DXCODE:BOOL=TRUE") 880 | endif() 881 | if (COTIRE_VERBOSE) 882 | list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") 883 | elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") 884 | list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") 885 | endif() 886 | endmacro() 887 | 888 | function (cotire_init_compile_cmd _cmdVar _language _compilerLauncher _compilerExe _compilerArg1) 889 | if (NOT _compilerLauncher) 890 | set (_compilerLauncher ${CMAKE_${_language}_COMPILER_LAUNCHER}) 891 | endif() 892 | if (NOT _compilerExe) 893 | set (_compilerExe "${CMAKE_${_language}_COMPILER}") 894 | endif() 895 | if (NOT _compilerArg1) 896 | set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) 897 | endif() 898 | if (WIN32) 899 | file (TO_NATIVE_PATH "${_compilerExe}" _compilerExe) 900 | endif() 901 | string (STRIP "${_compilerArg1}" _compilerArg1) 902 | if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") 903 | # compiler launcher is only supported for Makefile and Ninja 904 | set (${_cmdVar} ${_compilerLauncher} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) 905 | else() 906 | set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) 907 | endif() 908 | endfunction() 909 | 910 | macro (cotire_add_definitions_to_cmd _cmdVar _language) 911 | foreach (_definition ${ARGN}) 912 | if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") 913 | list (APPEND ${_cmdVar} "/D${_definition}") 914 | else() 915 | list (APPEND ${_cmdVar} "-D${_definition}") 916 | endif() 917 | endforeach() 918 | endmacro() 919 | 920 | function (cotire_add_includes_to_cmd _cmdVar _language _includesVar _systemIncludesVar) 921 | set (_includeDirs ${${_includesVar}} ${${_systemIncludesVar}}) 922 | if (_includeDirs) 923 | list (REMOVE_DUPLICATES _includeDirs) 924 | foreach (_include ${_includeDirs}) 925 | if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") 926 | file (TO_NATIVE_PATH "${_include}" _include) 927 | list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") 928 | else() 929 | set (_index -1) 930 | if ("${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" MATCHES ".+") 931 | list (FIND ${_systemIncludesVar} "${_include}" _index) 932 | endif() 933 | if (_index GREATER -1) 934 | list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") 935 | else() 936 | list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") 937 | endif() 938 | endif() 939 | endforeach() 940 | endif() 941 | set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) 942 | endfunction() 943 | 944 | function (cotire_add_frameworks_to_cmd _cmdVar _language _includesVar _systemIncludesVar) 945 | if (APPLE) 946 | set (_frameworkDirs "") 947 | foreach (_include ${${_includesVar}}) 948 | if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") 949 | get_filename_component(_frameworkDir "${_include}" DIRECTORY) 950 | list (APPEND _frameworkDirs "${_frameworkDir}") 951 | endif() 952 | endforeach() 953 | set (_systemFrameworkDirs "") 954 | foreach (_include ${${_systemIncludesVar}}) 955 | if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") 956 | get_filename_component(_frameworkDir "${_include}" DIRECTORY) 957 | list (APPEND _systemFrameworkDirs "${_frameworkDir}") 958 | endif() 959 | endforeach() 960 | if (_systemFrameworkDirs) 961 | list (APPEND _frameworkDirs ${_systemFrameworkDirs}) 962 | endif() 963 | if (_frameworkDirs) 964 | list (REMOVE_DUPLICATES _frameworkDirs) 965 | foreach (_frameworkDir ${_frameworkDirs}) 966 | set (_index -1) 967 | if ("${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}" MATCHES ".+") 968 | list (FIND _systemFrameworkDirs "${_frameworkDir}" _index) 969 | endif() 970 | if (_index GREATER -1) 971 | list (APPEND ${_cmdVar} "${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") 972 | else() 973 | list (APPEND ${_cmdVar} "${CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") 974 | endif() 975 | endforeach() 976 | endif() 977 | endif() 978 | set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) 979 | endfunction() 980 | 981 | macro (cotire_add_compile_flags_to_cmd _cmdVar) 982 | foreach (_flag ${ARGN}) 983 | list (APPEND ${_cmdVar} "${_flag}") 984 | endforeach() 985 | endmacro() 986 | 987 | function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) 988 | if (EXISTS "${_file}") 989 | set (_triggerFile "") 990 | foreach (_dependencyFile ${ARGN}) 991 | if (EXISTS "${_dependencyFile}") 992 | # IS_NEWER_THAN returns TRUE if both files have the same timestamp 993 | # thus we do the comparison in both directions to exclude ties 994 | if ("${_dependencyFile}" IS_NEWER_THAN "${_file}" AND 995 | NOT "${_file}" IS_NEWER_THAN "${_dependencyFile}") 996 | set (_triggerFile "${_dependencyFile}") 997 | break() 998 | endif() 999 | endif() 1000 | endforeach() 1001 | if (_triggerFile) 1002 | if (COTIRE_VERBOSE) 1003 | get_filename_component(_fileName "${_file}" NAME) 1004 | message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") 1005 | endif() 1006 | set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) 1007 | else() 1008 | if (COTIRE_VERBOSE) 1009 | get_filename_component(_fileName "${_file}" NAME) 1010 | message (STATUS "${_fileName} is up-to-date.") 1011 | endif() 1012 | set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) 1013 | endif() 1014 | else() 1015 | if (COTIRE_VERBOSE) 1016 | get_filename_component(_fileName "${_file}" NAME) 1017 | message (STATUS "${_fileName} does not exist yet.") 1018 | endif() 1019 | set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) 1020 | endif() 1021 | endfunction() 1022 | 1023 | macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) 1024 | set (${_relPathVar} "") 1025 | foreach (_includeDir ${_includeDirs}) 1026 | if (IS_DIRECTORY "${_includeDir}") 1027 | file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") 1028 | if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") 1029 | string (LENGTH "${${_relPathVar}}" _closestLen) 1030 | string (LENGTH "${_relPath}" _relLen) 1031 | if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) 1032 | set (${_relPathVar} "${_relPath}") 1033 | endif() 1034 | endif() 1035 | elseif ("${_includeDir}" STREQUAL "${_headerFile}") 1036 | # if path matches exactly, return short non-empty string 1037 | set (${_relPathVar} "1") 1038 | break() 1039 | endif() 1040 | endforeach() 1041 | endmacro() 1042 | 1043 | macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside) 1044 | # check header path against ignored and honored include directories 1045 | cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath) 1046 | if (_insideRelPath) 1047 | # header is inside, but could be become outside if there is a shorter outside match 1048 | cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath) 1049 | if (_outsideRelPath) 1050 | string (LENGTH "${_insideRelPath}" _insideRelPathLen) 1051 | string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) 1052 | if (_outsideRelPathLen LESS _insideRelPathLen) 1053 | set (${_headerIsInside} FALSE) 1054 | else() 1055 | set (${_headerIsInside} TRUE) 1056 | endif() 1057 | else() 1058 | set (${_headerIsInside} TRUE) 1059 | endif() 1060 | else() 1061 | # header is outside 1062 | set (${_headerIsInside} FALSE) 1063 | endif() 1064 | endmacro() 1065 | 1066 | macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) 1067 | if (NOT EXISTS "${_headerFile}") 1068 | set (${_headerIsIgnoredVar} TRUE) 1069 | elseif (IS_DIRECTORY "${_headerFile}") 1070 | set (${_headerIsIgnoredVar} TRUE) 1071 | elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed" AND "${_headerFile}" MATCHES "\\.h$") 1072 | # heuristic: ignore C headers with embedded parent directory references or "-fixed" or "_fixed" in path 1073 | # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation 1074 | # with the error message "error: no include path in which to search for header.h" 1075 | set (${_headerIsIgnoredVar} TRUE) 1076 | else() 1077 | set (${_headerIsIgnoredVar} FALSE) 1078 | endif() 1079 | endmacro() 1080 | 1081 | macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) 1082 | # check header file extension 1083 | cotire_get_source_file_extension("${_headerFile}" _headerFileExt) 1084 | set (${_headerIsIgnoredVar} FALSE) 1085 | if (_headerFileExt) 1086 | list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) 1087 | if (_index GREATER -1) 1088 | set (${_headerIsIgnoredVar} TRUE) 1089 | endif() 1090 | endif() 1091 | endmacro() 1092 | 1093 | macro (cotire_parse_line _line _headerFileVar _headerDepthVar) 1094 | if (MSVC) 1095 | # cl.exe /showIncludes produces different output, depending on the language pack used, e.g.: 1096 | # English: "Note: including file: C:\directory\file" 1097 | # German: "Hinweis: Einlesen der Datei: C:\directory\file" 1098 | # We use a very general regular expression, relying on the presence of the : characters 1099 | if (_line MATCHES "( +)([a-zA-Z]:[^:]+)$") 1100 | string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) 1101 | get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) 1102 | else() 1103 | set (${_headerFileVar} "") 1104 | set (${_headerDepthVar} 0) 1105 | endif() 1106 | else() 1107 | if (_line MATCHES "^(\\.+) (.*)$") 1108 | # GCC like output 1109 | string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) 1110 | if (IS_ABSOLUTE "${CMAKE_MATCH_2}") 1111 | set (${_headerFileVar} "${CMAKE_MATCH_2}") 1112 | else() 1113 | get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) 1114 | endif() 1115 | else() 1116 | set (${_headerFileVar} "") 1117 | set (${_headerDepthVar} 0) 1118 | endif() 1119 | endif() 1120 | endmacro() 1121 | 1122 | function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) 1123 | if (WIN32) 1124 | # prevent CMake macro invocation errors due to backslash characters in Windows paths 1125 | string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") 1126 | endif() 1127 | # canonize slashes 1128 | string (REPLACE "//" "/" _scanOutput "${_scanOutput}") 1129 | # prevent semicolon from being interpreted as a line separator 1130 | string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") 1131 | # then separate lines 1132 | string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") 1133 | list (LENGTH _scanOutput _len) 1134 | # remove duplicate lines to speed up parsing 1135 | list (REMOVE_DUPLICATES _scanOutput) 1136 | list (LENGTH _scanOutput _uniqueLen) 1137 | if (COTIRE_VERBOSE OR COTIRE_DEBUG) 1138 | message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") 1139 | if (_ignoredExtensions) 1140 | message (STATUS "Ignored extensions: ${_ignoredExtensions}") 1141 | endif() 1142 | if (_ignoredIncludeDirs) 1143 | message (STATUS "Ignored paths: ${_ignoredIncludeDirs}") 1144 | endif() 1145 | if (_honoredIncludeDirs) 1146 | message (STATUS "Included paths: ${_honoredIncludeDirs}") 1147 | endif() 1148 | endif() 1149 | set (_sourceFiles ${ARGN}) 1150 | set (_selectedIncludes "") 1151 | set (_unparsedLines "") 1152 | # stack keeps track of inside/outside project status of processed header files 1153 | set (_headerIsInsideStack "") 1154 | foreach (_line IN LISTS _scanOutput) 1155 | if (_line) 1156 | cotire_parse_line("${_line}" _headerFile _headerDepth) 1157 | if (_headerFile) 1158 | cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside) 1159 | if (COTIRE_DEBUG) 1160 | message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") 1161 | endif() 1162 | # update stack 1163 | list (LENGTH _headerIsInsideStack _stackLen) 1164 | if (_headerDepth GREATER _stackLen) 1165 | math (EXPR _stackLen "${_stackLen} + 1") 1166 | foreach (_index RANGE ${_stackLen} ${_headerDepth}) 1167 | list (APPEND _headerIsInsideStack ${_headerIsInside}) 1168 | endforeach() 1169 | else() 1170 | foreach (_index RANGE ${_headerDepth} ${_stackLen}) 1171 | list (REMOVE_AT _headerIsInsideStack -1) 1172 | endforeach() 1173 | list (APPEND _headerIsInsideStack ${_headerIsInside}) 1174 | endif() 1175 | if (COTIRE_DEBUG) 1176 | message (STATUS "${_headerIsInsideStack}") 1177 | endif() 1178 | # header is a candidate if it is outside project 1179 | if (NOT _headerIsInside) 1180 | # get parent header file's inside/outside status 1181 | if (_headerDepth GREATER 1) 1182 | math (EXPR _index "${_headerDepth} - 2") 1183 | list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) 1184 | else() 1185 | set (_parentHeaderIsInside TRUE) 1186 | endif() 1187 | # select header file if parent header file is inside project 1188 | # (e.g., a project header file that includes a standard header file) 1189 | if (_parentHeaderIsInside) 1190 | cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) 1191 | if (NOT _headerIsIgnored) 1192 | cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) 1193 | if (NOT _headerIsIgnored) 1194 | list (APPEND _selectedIncludes "${_headerFile}") 1195 | else() 1196 | # fix header's inside status on stack, it is ignored by extension now 1197 | list (REMOVE_AT _headerIsInsideStack -1) 1198 | list (APPEND _headerIsInsideStack TRUE) 1199 | endif() 1200 | endif() 1201 | if (COTIRE_DEBUG) 1202 | message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") 1203 | endif() 1204 | endif() 1205 | endif() 1206 | else() 1207 | if (MSVC) 1208 | # for cl.exe do not keep unparsed lines which solely consist of a source file name 1209 | string (FIND "${_sourceFiles}" "${_line}" _index) 1210 | if (_index LESS 0) 1211 | list (APPEND _unparsedLines "${_line}") 1212 | endif() 1213 | else() 1214 | list (APPEND _unparsedLines "${_line}") 1215 | endif() 1216 | endif() 1217 | endif() 1218 | endforeach() 1219 | list (REMOVE_DUPLICATES _selectedIncludes) 1220 | set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) 1221 | set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) 1222 | endfunction() 1223 | 1224 | function (cotire_scan_includes _includesVar) 1225 | set(_options "") 1226 | set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_VERSION LANGUAGE UNPARSED_LINES SCAN_RESULT) 1227 | set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES 1228 | IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) 1229 | cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) 1230 | set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) 1231 | if (NOT _option_LANGUAGE) 1232 | set (_option_LANGUAGE "CXX") 1233 | endif() 1234 | if (NOT _option_COMPILER_ID) 1235 | set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") 1236 | endif() 1237 | if (NOT _option_COMPILER_VERSION) 1238 | set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") 1239 | endif() 1240 | cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") 1241 | cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) 1242 | cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) 1243 | cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) 1244 | cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) 1245 | cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) 1246 | # only consider existing source files for scanning 1247 | set (_existingSourceFiles "") 1248 | foreach (_sourceFile ${_sourceFiles}) 1249 | if (EXISTS "${_sourceFile}") 1250 | list (APPEND _existingSourceFiles "${_sourceFile}") 1251 | endif() 1252 | endforeach() 1253 | if (NOT _existingSourceFiles) 1254 | set (${_includesVar} "" PARENT_SCOPE) 1255 | return() 1256 | endif() 1257 | # add source files to be scanned 1258 | if (WIN32) 1259 | foreach (_sourceFile ${_existingSourceFiles}) 1260 | file (TO_NATIVE_PATH "${_sourceFile}" _sourceFileNative) 1261 | list (APPEND _cmd "${_sourceFileNative}") 1262 | endforeach() 1263 | else() 1264 | list (APPEND _cmd ${_existingSourceFiles}) 1265 | endif() 1266 | if (COTIRE_VERBOSE) 1267 | message (STATUS "execute_process: ${_cmd}") 1268 | endif() 1269 | if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") 1270 | # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared 1271 | unset (ENV{VS_UNICODE_OUTPUT}) 1272 | endif() 1273 | execute_process( 1274 | COMMAND ${_cmd} 1275 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 1276 | RESULT_VARIABLE _result 1277 | OUTPUT_QUIET 1278 | ERROR_VARIABLE _output) 1279 | if (_result) 1280 | message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.") 1281 | endif() 1282 | cotire_parse_includes( 1283 | "${_option_LANGUAGE}" "${_output}" 1284 | "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" 1285 | "${_option_IGNORE_EXTENSIONS}" 1286 | _includes _unparsedLines 1287 | ${_sourceFiles}) 1288 | if (_option_INCLUDE_PRIORITY_PATH) 1289 | set (_sortedIncludes "") 1290 | foreach (_priorityPath ${_option_INCLUDE_PRIORITY_PATH}) 1291 | foreach (_include ${_includes}) 1292 | string (FIND ${_include} ${_priorityPath} _position) 1293 | if (_position GREATER -1) 1294 | list (APPEND _sortedIncludes ${_include}) 1295 | endif() 1296 | endforeach() 1297 | endforeach() 1298 | if (_sortedIncludes) 1299 | list (INSERT _includes 0 ${_sortedIncludes}) 1300 | list (REMOVE_DUPLICATES _includes) 1301 | endif() 1302 | endif() 1303 | set (${_includesVar} ${_includes} PARENT_SCOPE) 1304 | if (_option_UNPARSED_LINES) 1305 | set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) 1306 | endif() 1307 | if (_option_SCAN_RESULT) 1308 | set (${_option_SCAN_RESULT} ${_result} PARENT_SCOPE) 1309 | endif() 1310 | endfunction() 1311 | 1312 | macro (cotire_append_undefs _contentsVar) 1313 | set (_undefs ${ARGN}) 1314 | if (_undefs) 1315 | list (REMOVE_DUPLICATES _undefs) 1316 | foreach (_definition ${_undefs}) 1317 | list (APPEND ${_contentsVar} "#undef ${_definition}") 1318 | endforeach() 1319 | endif() 1320 | endmacro() 1321 | 1322 | macro (cotire_comment_str _language _commentText _commentVar) 1323 | if ("${_language}" STREQUAL "CMAKE") 1324 | set (${_commentVar} "# ${_commentText}") 1325 | else() 1326 | set (${_commentVar} "/* ${_commentText} */") 1327 | endif() 1328 | endmacro() 1329 | 1330 | function (cotire_write_file _language _file _contents _force) 1331 | get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) 1332 | cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) 1333 | cotire_comment_str("${_language}" "${_file}" _header2) 1334 | set (_contents "${_header1}\n${_header2}\n${_contents}") 1335 | if (COTIRE_DEBUG) 1336 | message (STATUS "${_contents}") 1337 | endif() 1338 | if (_force OR NOT EXISTS "${_file}") 1339 | file (WRITE "${_file}" "${_contents}") 1340 | else() 1341 | file (READ "${_file}" _oldContents) 1342 | if (NOT "${_oldContents}" STREQUAL "${_contents}") 1343 | file (WRITE "${_file}" "${_contents}") 1344 | else() 1345 | if (COTIRE_DEBUG) 1346 | message (STATUS "${_file} unchanged") 1347 | endif() 1348 | endif() 1349 | endif() 1350 | endfunction() 1351 | 1352 | function (cotire_generate_unity_source _unityFile) 1353 | set(_options "") 1354 | set(_oneValueArgs LANGUAGE) 1355 | set(_multiValueArgs 1356 | DEPENDS SOURCES_COMPILE_DEFINITIONS 1357 | PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE) 1358 | cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) 1359 | if (_option_DEPENDS) 1360 | cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) 1361 | if (_unityFileIsUpToDate) 1362 | return() 1363 | endif() 1364 | endif() 1365 | set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) 1366 | if (NOT _option_PRE_UNDEFS) 1367 | set (_option_PRE_UNDEFS "") 1368 | endif() 1369 | if (NOT _option_SOURCES_PRE_UNDEFS) 1370 | set (_option_SOURCES_PRE_UNDEFS "") 1371 | endif() 1372 | if (NOT _option_POST_UNDEFS) 1373 | set (_option_POST_UNDEFS "") 1374 | endif() 1375 | if (NOT _option_SOURCES_POST_UNDEFS) 1376 | set (_option_SOURCES_POST_UNDEFS "") 1377 | endif() 1378 | set (_contents "") 1379 | if (_option_PROLOGUE) 1380 | list (APPEND _contents ${_option_PROLOGUE}) 1381 | endif() 1382 | if (_option_LANGUAGE AND _sourceFiles) 1383 | if ("${_option_LANGUAGE}" STREQUAL "CXX") 1384 | list (APPEND _contents "#ifdef __cplusplus") 1385 | elseif ("${_option_LANGUAGE}" STREQUAL "C") 1386 | list (APPEND _contents "#ifndef __cplusplus") 1387 | endif() 1388 | endif() 1389 | set (_compileUndefinitions "") 1390 | foreach (_sourceFile ${_sourceFiles}) 1391 | cotire_get_source_compile_definitions( 1392 | "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions 1393 | ${_option_SOURCES_COMPILE_DEFINITIONS}) 1394 | cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) 1395 | cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) 1396 | if (_option_PRE_UNDEFS) 1397 | list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) 1398 | endif() 1399 | if (_sourcePreUndefs) 1400 | list (APPEND _compileUndefinitions ${_sourcePreUndefs}) 1401 | endif() 1402 | if (_compileUndefinitions) 1403 | cotire_append_undefs(_contents ${_compileUndefinitions}) 1404 | set (_compileUndefinitions "") 1405 | endif() 1406 | if (_sourcePostUndefs) 1407 | list (APPEND _compileUndefinitions ${_sourcePostUndefs}) 1408 | endif() 1409 | if (_option_POST_UNDEFS) 1410 | list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) 1411 | endif() 1412 | foreach (_definition ${_compileDefinitions}) 1413 | if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$") 1414 | list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") 1415 | list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") 1416 | else() 1417 | list (APPEND _contents "#define ${_definition}") 1418 | list (INSERT _compileUndefinitions 0 "${_definition}") 1419 | endif() 1420 | endforeach() 1421 | # use absolute path as source file location 1422 | get_filename_component(_sourceFileLocation "${_sourceFile}" ABSOLUTE) 1423 | if (WIN32) 1424 | file (TO_NATIVE_PATH "${_sourceFileLocation}" _sourceFileLocation) 1425 | endif() 1426 | list (APPEND _contents "#include \"${_sourceFileLocation}\"") 1427 | endforeach() 1428 | if (_compileUndefinitions) 1429 | cotire_append_undefs(_contents ${_compileUndefinitions}) 1430 | set (_compileUndefinitions "") 1431 | endif() 1432 | if (_option_LANGUAGE AND _sourceFiles) 1433 | list (APPEND _contents "#endif") 1434 | endif() 1435 | if (_option_EPILOGUE) 1436 | list (APPEND _contents ${_option_EPILOGUE}) 1437 | endif() 1438 | list (APPEND _contents "") 1439 | string (REPLACE ";" "\n" _contents "${_contents}") 1440 | if (COTIRE_VERBOSE) 1441 | message ("${_contents}") 1442 | endif() 1443 | cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) 1444 | endfunction() 1445 | 1446 | function (cotire_generate_prefix_header _prefixFile) 1447 | set(_options "") 1448 | set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION) 1449 | set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS 1450 | INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH 1451 | IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) 1452 | cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) 1453 | if (NOT _option_COMPILER_ID) 1454 | set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") 1455 | endif() 1456 | if (NOT _option_COMPILER_VERSION) 1457 | set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") 1458 | endif() 1459 | if (_option_DEPENDS) 1460 | cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) 1461 | if (_prefixFileIsUpToDate) 1462 | # create empty log file 1463 | set (_unparsedLinesFile "${_prefixFile}.log") 1464 | file (WRITE "${_unparsedLinesFile}" "") 1465 | return() 1466 | endif() 1467 | endif() 1468 | set (_prologue "") 1469 | set (_epilogue "") 1470 | if (_option_COMPILER_ID MATCHES "Clang") 1471 | set (_prologue "#pragma clang system_header") 1472 | elseif (_option_COMPILER_ID MATCHES "GNU") 1473 | set (_prologue "#pragma GCC system_header") 1474 | elseif (_option_COMPILER_ID MATCHES "MSVC") 1475 | set (_prologue "#pragma warning(push, 0)") 1476 | set (_epilogue "#pragma warning(pop)") 1477 | elseif (_option_COMPILER_ID MATCHES "Intel") 1478 | # Intel compiler requires hdrstop pragma to stop generating PCH file 1479 | set (_epilogue "#pragma hdrstop") 1480 | endif() 1481 | set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) 1482 | cotire_scan_includes(_selectedHeaders ${_sourceFiles} 1483 | LANGUAGE "${_option_LANGUAGE}" 1484 | COMPILER_LAUNCHER "${_option_COMPILER_LAUNCHER}" 1485 | COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" 1486 | COMPILER_ARG1 "${_option_COMPILER_ARG1}" 1487 | COMPILER_ID "${_option_COMPILER_ID}" 1488 | COMPILER_VERSION "${_option_COMPILER_VERSION}" 1489 | COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} 1490 | COMPILE_FLAGS ${_option_COMPILE_FLAGS} 1491 | INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} 1492 | SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES} 1493 | IGNORE_PATH ${_option_IGNORE_PATH} 1494 | INCLUDE_PATH ${_option_INCLUDE_PATH} 1495 | IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} 1496 | INCLUDE_PRIORITY_PATH ${_option_INCLUDE_PRIORITY_PATH} 1497 | UNPARSED_LINES _unparsedLines 1498 | SCAN_RESULT _scanResult) 1499 | cotire_generate_unity_source("${_prefixFile}" 1500 | PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) 1501 | set (_unparsedLinesFile "${_prefixFile}.log") 1502 | if (_unparsedLines) 1503 | if (COTIRE_VERBOSE OR _scanResult OR NOT _selectedHeaders) 1504 | list (LENGTH _unparsedLines _skippedLineCount) 1505 | if (WIN32) 1506 | file (TO_NATIVE_PATH "${_unparsedLinesFile}" _unparsedLinesLogPath) 1507 | else() 1508 | set (_unparsedLinesLogPath "${_unparsedLinesFile}") 1509 | endif() 1510 | message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesLogPath}") 1511 | endif() 1512 | string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") 1513 | endif() 1514 | file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}\n") 1515 | endfunction() 1516 | 1517 | function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) 1518 | set (_flags ${${_flagsVar}}) 1519 | if (_compilerID MATCHES "MSVC") 1520 | # cl.exe options used 1521 | # /nologo suppresses display of sign-on banner 1522 | # /TC treat all files named on the command line as C source files 1523 | # /TP treat all files named on the command line as C++ source files 1524 | # /EP preprocess to stdout without #line directives 1525 | # /showIncludes list include files 1526 | set (_sourceFileTypeC "/TC") 1527 | set (_sourceFileTypeCXX "/TP") 1528 | if (_flags) 1529 | # append to list 1530 | list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) 1531 | else() 1532 | # return as a flag string 1533 | set (_flags "${_sourceFileType${_language}} /EP /showIncludes") 1534 | endif() 1535 | elseif (_compilerID MATCHES "GNU") 1536 | # GCC options used 1537 | # -H print the name of each header file used 1538 | # -E invoke preprocessor 1539 | # -fdirectives-only do not expand macros, requires GCC >= 4.3 1540 | if (_flags) 1541 | # append to list 1542 | list (APPEND _flags -H -E) 1543 | if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") 1544 | list (APPEND _flags -fdirectives-only) 1545 | endif() 1546 | else() 1547 | # return as a flag string 1548 | set (_flags "-H -E") 1549 | if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") 1550 | set (_flags "${_flags} -fdirectives-only") 1551 | endif() 1552 | endif() 1553 | elseif (_compilerID MATCHES "Clang") 1554 | if (UNIX) 1555 | # Clang options used 1556 | # -H print the name of each header file used 1557 | # -E invoke preprocessor 1558 | # -fno-color-diagnostics do not print diagnostics in color 1559 | # -Eonly just run preprocessor, no output 1560 | if (_flags) 1561 | # append to list 1562 | list (APPEND _flags -H -E -fno-color-diagnostics -Xclang -Eonly) 1563 | else() 1564 | # return as a flag string 1565 | set (_flags "-H -E -fno-color-diagnostics -Xclang -Eonly") 1566 | endif() 1567 | elseif (WIN32) 1568 | # Clang-cl.exe options used 1569 | # /TC treat all files named on the command line as C source files 1570 | # /TP treat all files named on the command line as C++ source files 1571 | # /EP preprocess to stdout without #line directives 1572 | # -H print the name of each header file used 1573 | # -fno-color-diagnostics do not print diagnostics in color 1574 | # -Eonly just run preprocessor, no output 1575 | set (_sourceFileTypeC "/TC") 1576 | set (_sourceFileTypeCXX "/TP") 1577 | if (_flags) 1578 | # append to list 1579 | list (APPEND _flags "${_sourceFileType${_language}}" /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly) 1580 | else() 1581 | # return as a flag string 1582 | set (_flags "${_sourceFileType${_language}} /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly") 1583 | endif() 1584 | endif() 1585 | elseif (_compilerID MATCHES "Intel") 1586 | if (WIN32) 1587 | # Windows Intel options used 1588 | # /nologo do not display compiler version information 1589 | # /QH display the include file order 1590 | # /EP preprocess to stdout, omitting #line directives 1591 | # /TC process all source or unrecognized file types as C source files 1592 | # /TP process all source or unrecognized file types as C++ source files 1593 | set (_sourceFileTypeC "/TC") 1594 | set (_sourceFileTypeCXX "/TP") 1595 | if (_flags) 1596 | # append to list 1597 | list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH) 1598 | else() 1599 | # return as a flag string 1600 | set (_flags "${_sourceFileType${_language}} /EP /QH") 1601 | endif() 1602 | else() 1603 | # Linux / Mac OS X Intel options used 1604 | # -H print the name of each header file used 1605 | # -EP preprocess to stdout, omitting #line directives 1606 | # -Kc++ process all source or unrecognized file types as C++ source files 1607 | if (_flags) 1608 | # append to list 1609 | if ("${_language}" STREQUAL "CXX") 1610 | list (APPEND _flags -Kc++) 1611 | endif() 1612 | list (APPEND _flags -H -EP) 1613 | else() 1614 | # return as a flag string 1615 | if ("${_language}" STREQUAL "CXX") 1616 | set (_flags "-Kc++ ") 1617 | endif() 1618 | set (_flags "${_flags}-H -EP") 1619 | endif() 1620 | endif() 1621 | else() 1622 | message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") 1623 | endif() 1624 | set (${_flagsVar} ${_flags} PARENT_SCOPE) 1625 | endfunction() 1626 | 1627 | function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) 1628 | set (_flags ${${_flagsVar}}) 1629 | if (_compilerID MATCHES "MSVC") 1630 | file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) 1631 | file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) 1632 | file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) 1633 | # cl.exe options used 1634 | # /Yc creates a precompiled header file 1635 | # /Fp specifies precompiled header binary file name 1636 | # /FI forces inclusion of file 1637 | # /TC treat all files named on the command line as C source files 1638 | # /TP treat all files named on the command line as C++ source files 1639 | # /Zs syntax check only 1640 | # /Zm precompiled header memory allocation scaling factor 1641 | set (_sourceFileTypeC "/TC") 1642 | set (_sourceFileTypeCXX "/TP") 1643 | if (_flags) 1644 | # append to list 1645 | list (APPEND _flags /nologo "${_sourceFileType${_language}}" 1646 | "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") 1647 | if (COTIRE_PCH_MEMORY_SCALING_FACTOR) 1648 | list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") 1649 | endif() 1650 | else() 1651 | # return as a flag string 1652 | set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") 1653 | if (COTIRE_PCH_MEMORY_SCALING_FACTOR) 1654 | set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") 1655 | endif() 1656 | endif() 1657 | elseif (_compilerID MATCHES "GNU") 1658 | # GCC options used 1659 | # -x specify the source language 1660 | # -c compile but do not link 1661 | # -o place output in file 1662 | # note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may 1663 | # alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings) 1664 | set (_xLanguage_C "c-header") 1665 | set (_xLanguage_CXX "c++-header") 1666 | if (_flags) 1667 | # append to list 1668 | list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") 1669 | else() 1670 | # return as a flag string 1671 | set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") 1672 | endif() 1673 | elseif (_compilerID MATCHES "Clang") 1674 | if (UNIX) 1675 | # Clang options used 1676 | # -x specify the source language 1677 | # -c compile but do not link 1678 | # -o place output in file 1679 | # -fno-pch-timestamp disable inclusion of timestamp in precompiled headers (clang 4.0.0+) 1680 | set (_xLanguage_C "c-header") 1681 | set (_xLanguage_CXX "c++-header") 1682 | if (_flags) 1683 | # append to list 1684 | list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") 1685 | if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") 1686 | list (APPEND _flags -Xclang -fno-pch-timestamp) 1687 | endif() 1688 | else() 1689 | # return as a flag string 1690 | set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") 1691 | if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") 1692 | set (_flags "${_flags} -Xclang -fno-pch-timestamp") 1693 | endif() 1694 | endif() 1695 | elseif (WIN32) 1696 | # Clang-cl.exe options used 1697 | # /Yc creates a precompiled header file 1698 | # /Fp specifies precompiled header binary file name 1699 | # /FI forces inclusion of file 1700 | # /Zs syntax check only 1701 | # /TC treat all files named on the command line as C source files 1702 | # /TP treat all files named on the command line as C++ source files 1703 | set (_sourceFileTypeC "/TC") 1704 | set (_sourceFileTypeCXX "/TP") 1705 | if (_flags) 1706 | # append to list 1707 | list (APPEND _flags "${_sourceFileType${_language}}" 1708 | "/Yc${_prefixFile}" "/Fp${_pchFile}" "/FI${_prefixFile}" /Zs "${_hostFile}") 1709 | else() 1710 | # return as a flag string 1711 | set (_flags "/Yc\"${_prefixFile}\" /Fp\"${_pchFile}\" /FI\"${_prefixFile}\"") 1712 | endif() 1713 | endif() 1714 | elseif (_compilerID MATCHES "Intel") 1715 | if (WIN32) 1716 | file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) 1717 | file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) 1718 | file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) 1719 | # Windows Intel options used 1720 | # /nologo do not display compiler version information 1721 | # /Yc create a precompiled header (PCH) file 1722 | # /Fp specify a path or file name for precompiled header files 1723 | # /FI tells the preprocessor to include a specified file name as the header file 1724 | # /TC process all source or unrecognized file types as C source files 1725 | # /TP process all source or unrecognized file types as C++ source files 1726 | # /Zs syntax check only 1727 | # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) 1728 | set (_sourceFileTypeC "/TC") 1729 | set (_sourceFileTypeCXX "/TP") 1730 | if (_flags) 1731 | # append to list 1732 | list (APPEND _flags /nologo "${_sourceFileType${_language}}" 1733 | "/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") 1734 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1735 | list (APPEND _flags "/Wpch-messages") 1736 | endif() 1737 | else() 1738 | # return as a flag string 1739 | set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") 1740 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1741 | set (_flags "${_flags} /Wpch-messages") 1742 | endif() 1743 | endif() 1744 | else() 1745 | # Linux / Mac OS X Intel options used 1746 | # -pch-dir location for precompiled header files 1747 | # -pch-create name of the precompiled header (PCH) to create 1748 | # -Kc++ process all source or unrecognized file types as C++ source files 1749 | # -fsyntax-only check only for correct syntax 1750 | # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) 1751 | get_filename_component(_pchDir "${_pchFile}" DIRECTORY) 1752 | get_filename_component(_pchName "${_pchFile}" NAME) 1753 | set (_xLanguage_C "c-header") 1754 | set (_xLanguage_CXX "c++-header") 1755 | set (_pchSuppressMessages FALSE) 1756 | if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") 1757 | set(_pchSuppressMessages TRUE) 1758 | endif() 1759 | if (_flags) 1760 | # append to list 1761 | if ("${_language}" STREQUAL "CXX") 1762 | list (APPEND _flags -Kc++) 1763 | endif() 1764 | list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-create "${_pchName}" -fsyntax-only "${_hostFile}") 1765 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1766 | if (NOT _pchSuppressMessages) 1767 | list (APPEND _flags -Wpch-messages) 1768 | endif() 1769 | endif() 1770 | else() 1771 | # return as a flag string 1772 | set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"") 1773 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1774 | if (NOT _pchSuppressMessages) 1775 | set (_flags "${_flags} -Wpch-messages") 1776 | endif() 1777 | endif() 1778 | endif() 1779 | endif() 1780 | else() 1781 | message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") 1782 | endif() 1783 | set (${_flagsVar} ${_flags} PARENT_SCOPE) 1784 | endfunction() 1785 | 1786 | function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) 1787 | set (_flags ${${_flagsVar}}) 1788 | if (_compilerID MATCHES "MSVC") 1789 | file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) 1790 | # cl.exe options used 1791 | # /Yu uses a precompiled header file during build 1792 | # /Fp specifies precompiled header binary file name 1793 | # /FI forces inclusion of file 1794 | # /Zm precompiled header memory allocation scaling factor 1795 | if (_pchFile) 1796 | file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) 1797 | if (_flags) 1798 | # append to list 1799 | list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") 1800 | if (COTIRE_PCH_MEMORY_SCALING_FACTOR) 1801 | list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") 1802 | endif() 1803 | else() 1804 | # return as a flag string 1805 | set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") 1806 | if (COTIRE_PCH_MEMORY_SCALING_FACTOR) 1807 | set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") 1808 | endif() 1809 | endif() 1810 | else() 1811 | # no precompiled header, force inclusion of prefix header 1812 | if (_flags) 1813 | # append to list 1814 | list (APPEND _flags "/FI${_prefixFileNative}") 1815 | else() 1816 | # return as a flag string 1817 | set (_flags "/FI\"${_prefixFileNative}\"") 1818 | endif() 1819 | endif() 1820 | elseif (_compilerID MATCHES "GNU") 1821 | # GCC options used 1822 | # -include process include file as the first line of the primary source file 1823 | # -Winvalid-pch warns if precompiled header is found but cannot be used 1824 | # note: ccache requires the -include flag to be used in order to process precompiled header correctly 1825 | if (_flags) 1826 | # append to list 1827 | list (APPEND _flags -Winvalid-pch -include "${_prefixFile}") 1828 | else() 1829 | # return as a flag string 1830 | set (_flags "-Winvalid-pch -include \"${_prefixFile}\"") 1831 | endif() 1832 | elseif (_compilerID MATCHES "Clang") 1833 | if (UNIX) 1834 | # Clang options used 1835 | # -include process include file as the first line of the primary source file 1836 | # note: ccache requires the -include flag to be used in order to process precompiled header correctly 1837 | if (_flags) 1838 | # append to list 1839 | list (APPEND _flags -include "${_prefixFile}") 1840 | else() 1841 | # return as a flag string 1842 | set (_flags "-include \"${_prefixFile}\"") 1843 | endif() 1844 | elseif (WIN32) 1845 | # Clang-cl.exe options used 1846 | # /Yu uses a precompiled header file during build 1847 | # /Fp specifies precompiled header binary file name 1848 | # /FI forces inclusion of file 1849 | if (_pchFile) 1850 | if (_flags) 1851 | # append to list 1852 | list (APPEND _flags "/Yu${_prefixFile}" "/Fp${_pchFile}" "/FI${_prefixFile}") 1853 | else() 1854 | # return as a flag string 1855 | set (_flags "/Yu\"${_prefixFile}\" /Fp\"${_pchFile}\" /FI\"${_prefixFile}\"") 1856 | endif() 1857 | else() 1858 | # no precompiled header, force inclusion of prefix header 1859 | if (_flags) 1860 | # append to list 1861 | list (APPEND _flags "/FI${_prefixFile}") 1862 | else() 1863 | # return as a flag string 1864 | set (_flags "/FI\"${_prefixFile}\"") 1865 | endif() 1866 | endif() 1867 | endif() 1868 | elseif (_compilerID MATCHES "Intel") 1869 | if (WIN32) 1870 | file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) 1871 | # Windows Intel options used 1872 | # /Yu use a precompiled header (PCH) file 1873 | # /Fp specify a path or file name for precompiled header files 1874 | # /FI tells the preprocessor to include a specified file name as the header file 1875 | # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) 1876 | if (_pchFile) 1877 | file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) 1878 | if (_flags) 1879 | # append to list 1880 | list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") 1881 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1882 | list (APPEND _flags "/Wpch-messages") 1883 | endif() 1884 | else() 1885 | # return as a flag string 1886 | set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") 1887 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1888 | set (_flags "${_flags} /Wpch-messages") 1889 | endif() 1890 | endif() 1891 | else() 1892 | # no precompiled header, force inclusion of prefix header 1893 | if (_flags) 1894 | # append to list 1895 | list (APPEND _flags "/FI${_prefixFileNative}") 1896 | else() 1897 | # return as a flag string 1898 | set (_flags "/FI\"${_prefixFileNative}\"") 1899 | endif() 1900 | endif() 1901 | else() 1902 | # Linux / Mac OS X Intel options used 1903 | # -pch-dir location for precompiled header files 1904 | # -pch-use name of the precompiled header (PCH) to use 1905 | # -include process include file as the first line of the primary source file 1906 | # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) 1907 | if (_pchFile) 1908 | get_filename_component(_pchDir "${_pchFile}" DIRECTORY) 1909 | get_filename_component(_pchName "${_pchFile}" NAME) 1910 | set (_pchSuppressMessages FALSE) 1911 | if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") 1912 | set(_pchSuppressMessages TRUE) 1913 | endif() 1914 | if (_flags) 1915 | # append to list 1916 | list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-use "${_pchName}") 1917 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1918 | if (NOT _pchSuppressMessages) 1919 | list (APPEND _flags -Wpch-messages) 1920 | endif() 1921 | endif() 1922 | else() 1923 | # return as a flag string 1924 | set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"") 1925 | if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") 1926 | if (NOT _pchSuppressMessages) 1927 | set (_flags "${_flags} -Wpch-messages") 1928 | endif() 1929 | endif() 1930 | endif() 1931 | else() 1932 | # no precompiled header, force inclusion of prefix header 1933 | if (_flags) 1934 | # append to list 1935 | list (APPEND _flags -include "${_prefixFile}") 1936 | else() 1937 | # return as a flag string 1938 | set (_flags "-include \"${_prefixFile}\"") 1939 | endif() 1940 | endif() 1941 | endif() 1942 | else() 1943 | message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") 1944 | endif() 1945 | set (${_flagsVar} ${_flags} PARENT_SCOPE) 1946 | endfunction() 1947 | 1948 | function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) 1949 | set(_options "") 1950 | set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION LANGUAGE) 1951 | set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS COMPILER_LAUNCHER) 1952 | cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) 1953 | if (NOT _option_LANGUAGE) 1954 | set (_option_LANGUAGE "CXX") 1955 | endif() 1956 | if (NOT _option_COMPILER_ID) 1957 | set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") 1958 | endif() 1959 | if (NOT _option_COMPILER_VERSION) 1960 | set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") 1961 | endif() 1962 | cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") 1963 | cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) 1964 | cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) 1965 | cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) 1966 | cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) 1967 | cotire_add_pch_compilation_flags( 1968 | "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" 1969 | "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) 1970 | if (COTIRE_VERBOSE) 1971 | message (STATUS "execute_process: ${_cmd}") 1972 | endif() 1973 | if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") 1974 | # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared 1975 | unset (ENV{VS_UNICODE_OUTPUT}) 1976 | elseif (_option_COMPILER_ID MATCHES "Clang" AND _option_COMPILER_VERSION VERSION_LESS "4.0.0") 1977 | if (_option_COMPILER_LAUNCHER MATCHES "ccache" OR 1978 | _option_COMPILER_EXECUTABLE MATCHES "ccache") 1979 | # Newer versions of Clang embed a compilation timestamp into the precompiled header binary, 1980 | # which results in "file has been modified since the precompiled header was built" errors if ccache is used. 1981 | # We work around the problem by disabling ccache upon pre-compiling the prefix header. 1982 | set (ENV{CCACHE_DISABLE} "true") 1983 | endif() 1984 | endif() 1985 | execute_process( 1986 | COMMAND ${_cmd} 1987 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 1988 | RESULT_VARIABLE _result) 1989 | if (_result) 1990 | message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.") 1991 | endif() 1992 | endfunction() 1993 | 1994 | function (cotire_check_precompiled_header_support _language _target _msgVar) 1995 | set (_unsupportedCompiler 1996 | "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}") 1997 | if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") 1998 | # PCH supported since Visual Studio C++ 6.0 1999 | # and CMake does not support an earlier version 2000 | set (${_msgVar} "" PARENT_SCOPE) 2001 | elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") 2002 | # GCC PCH support requires version >= 3.4 2003 | if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") 2004 | set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) 2005 | else() 2006 | set (${_msgVar} "" PARENT_SCOPE) 2007 | endif() 2008 | elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") 2009 | if (UNIX) 2010 | # all Unix Clang versions have PCH support 2011 | set (${_msgVar} "" PARENT_SCOPE) 2012 | elseif (WIN32) 2013 | # only clang-cl is supported under Windows 2014 | get_filename_component(_compilerName "${CMAKE_${_language}_COMPILER}" NAME_WE) 2015 | if (NOT _compilerName MATCHES "cl$") 2016 | set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}. Use clang-cl instead." PARENT_SCOPE) 2017 | endif() 2018 | endif() 2019 | elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") 2020 | # Intel PCH support requires version >= 8.0.0 2021 | if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0") 2022 | set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) 2023 | else() 2024 | set (${_msgVar} "" PARENT_SCOPE) 2025 | endif() 2026 | else() 2027 | set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE) 2028 | endif() 2029 | # check if ccache is used as a compiler launcher 2030 | get_target_property(_launcher ${_target} ${_language}_COMPILER_LAUNCHER) 2031 | get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" REALPATH) 2032 | if (_realCompilerExe MATCHES "ccache" OR _launcher MATCHES "ccache") 2033 | # verify that ccache configuration is compatible with precompiled headers 2034 | # always check environment variable CCACHE_SLOPPINESS, because earlier versions of ccache 2035 | # do not report the "sloppiness" setting correctly upon printing ccache configuration 2036 | if (DEFINED ENV{CCACHE_SLOPPINESS}) 2037 | if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "pch_defines" OR 2038 | NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros") 2039 | set (${_msgVar} 2040 | "ccache requires the environment variable CCACHE_SLOPPINESS to be set to \"pch_defines,time_macros\"." 2041 | PARENT_SCOPE) 2042 | endif() 2043 | else() 2044 | if (_realCompilerExe MATCHES "ccache") 2045 | set (_ccacheExe "${_realCompilerExe}") 2046 | else() 2047 | set (_ccacheExe "${_launcher}") 2048 | endif() 2049 | execute_process( 2050 | COMMAND "${_ccacheExe}" "--print-config" 2051 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 2052 | RESULT_VARIABLE _result 2053 | OUTPUT_VARIABLE _ccacheConfig OUTPUT_STRIP_TRAILING_WHITESPACE 2054 | ERROR_QUIET) 2055 | if (_result) 2056 | set (${_msgVar} "ccache configuration cannot be determined." PARENT_SCOPE) 2057 | elseif (NOT _ccacheConfig MATCHES "sloppiness.*=.*time_macros" OR 2058 | NOT _ccacheConfig MATCHES "sloppiness.*=.*pch_defines") 2059 | set (${_msgVar} 2060 | "ccache requires configuration setting \"sloppiness\" to be set to \"pch_defines,time_macros\"." 2061 | PARENT_SCOPE) 2062 | endif() 2063 | endif() 2064 | endif() 2065 | if (APPLE) 2066 | # PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64) 2067 | cotire_get_configuration_types(_configs) 2068 | foreach (_config ${_configs}) 2069 | set (_targetFlags "") 2070 | cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) 2071 | cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags}) 2072 | list (LENGTH _architectures _numberOfArchitectures) 2073 | if (_numberOfArchitectures GREATER 1) 2074 | string (REPLACE ";" ", " _architectureStr "${_architectures}") 2075 | set (${_msgVar} 2076 | "Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})." 2077 | PARENT_SCOPE) 2078 | break() 2079 | endif() 2080 | endforeach() 2081 | endif() 2082 | endfunction() 2083 | 2084 | macro (cotire_get_intermediate_dir _cotireDir) 2085 | # ${CMAKE_CFG_INTDIR} may reference a build-time variable when using a generator which supports configuration types 2086 | get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) 2087 | endmacro() 2088 | 2089 | macro (cotire_setup_file_extension_variables) 2090 | set (_unityFileExt_C ".c") 2091 | set (_unityFileExt_CXX ".cxx") 2092 | set (_prefixFileExt_C ".h") 2093 | set (_prefixFileExt_CXX ".hxx") 2094 | set (_prefixSourceFileExt_C ".c") 2095 | set (_prefixSourceFileExt_CXX ".cxx") 2096 | endmacro() 2097 | 2098 | function (cotire_make_single_unity_source_file_path _language _target _unityFileVar) 2099 | cotire_setup_file_extension_variables() 2100 | if (NOT DEFINED _unityFileExt_${_language}) 2101 | set (${_unityFileVar} "" PARENT_SCOPE) 2102 | return() 2103 | endif() 2104 | set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") 2105 | set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") 2106 | cotire_get_intermediate_dir(_baseDir) 2107 | set (_unityFile "${_baseDir}/${_unityFileName}") 2108 | set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE) 2109 | endfunction() 2110 | 2111 | function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar) 2112 | cotire_setup_file_extension_variables() 2113 | if (NOT DEFINED _unityFileExt_${_language}) 2114 | set (${_unityFileVar} "" PARENT_SCOPE) 2115 | return() 2116 | endif() 2117 | set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") 2118 | cotire_get_intermediate_dir(_baseDir) 2119 | set (_startIndex 0) 2120 | set (_index 0) 2121 | set (_unityFiles "") 2122 | set (_sourceFiles ${ARGN}) 2123 | foreach (_sourceFile ${_sourceFiles}) 2124 | get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) 2125 | math (EXPR _unityFileCount "${_index} - ${_startIndex}") 2126 | if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) 2127 | if (_index GREATER 0) 2128 | # start new unity file segment 2129 | math (EXPR _endIndex "${_index} - 1") 2130 | set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") 2131 | list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") 2132 | endif() 2133 | set (_startIndex ${_index}) 2134 | endif() 2135 | math (EXPR _index "${_index} + 1") 2136 | endforeach() 2137 | list (LENGTH _sourceFiles _numberOfSources) 2138 | if (_startIndex EQUAL 0) 2139 | # there is only a single unity file 2140 | cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles) 2141 | elseif (_startIndex LESS _numberOfSources) 2142 | # end with final unity file segment 2143 | math (EXPR _endIndex "${_index} - 1") 2144 | set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") 2145 | list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") 2146 | endif() 2147 | set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) 2148 | if (COTIRE_DEBUG AND _unityFiles) 2149 | message (STATUS "unity files: ${_unityFiles}") 2150 | endif() 2151 | endfunction() 2152 | 2153 | function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar) 2154 | cotire_setup_file_extension_variables() 2155 | if (NOT DEFINED _unityFileExt_${_language}) 2156 | set (${_prefixFileVar} "" PARENT_SCOPE) 2157 | return() 2158 | endif() 2159 | set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") 2160 | set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") 2161 | string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}") 2162 | string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}") 2163 | set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE) 2164 | endfunction() 2165 | 2166 | function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar) 2167 | cotire_setup_file_extension_variables() 2168 | if (NOT DEFINED _prefixSourceFileExt_${_language}) 2169 | set (${_prefixSourceFileVar} "" PARENT_SCOPE) 2170 | return() 2171 | endif() 2172 | string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}") 2173 | set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE) 2174 | endfunction() 2175 | 2176 | function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) 2177 | cotire_setup_file_extension_variables() 2178 | if (NOT _language) 2179 | set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") 2180 | set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") 2181 | elseif (DEFINED _prefixFileExt_${_language}) 2182 | set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") 2183 | set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") 2184 | else() 2185 | set (_prefixFileBaseName "") 2186 | set (_prefixFileName "") 2187 | endif() 2188 | set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) 2189 | set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) 2190 | endfunction() 2191 | 2192 | function (cotire_make_prefix_file_path _language _target _prefixFileVar) 2193 | cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) 2194 | set (${_prefixFileVar} "" PARENT_SCOPE) 2195 | if (_prefixFileName) 2196 | if (NOT _language) 2197 | set (_language "C") 2198 | endif() 2199 | if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel|MSVC") 2200 | cotire_get_intermediate_dir(_baseDir) 2201 | set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) 2202 | endif() 2203 | endif() 2204 | endfunction() 2205 | 2206 | function (cotire_make_pch_file_path _language _target _pchFileVar) 2207 | cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) 2208 | set (${_pchFileVar} "" PARENT_SCOPE) 2209 | if (_prefixFileBaseName AND _prefixFileName) 2210 | cotire_check_precompiled_header_support("${_language}" "${_target}" _msg) 2211 | if (NOT _msg) 2212 | if (XCODE) 2213 | # For Xcode, we completely hand off the compilation of the prefix header to the IDE 2214 | return() 2215 | endif() 2216 | cotire_get_intermediate_dir(_baseDir) 2217 | if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") 2218 | # MSVC uses the extension .pch added to the prefix header base name 2219 | set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) 2220 | elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") 2221 | # Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended 2222 | set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE) 2223 | elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") 2224 | # GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended 2225 | set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) 2226 | elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") 2227 | # Intel uses the extension .pchi added to the prefix header base name 2228 | set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE) 2229 | endif() 2230 | endif() 2231 | endif() 2232 | endfunction() 2233 | 2234 | function (cotire_select_unity_source_files _unityFile _sourcesVar) 2235 | set (_sourceFiles ${ARGN}) 2236 | if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") 2237 | set (_startIndex ${CMAKE_MATCH_1}) 2238 | set (_endIndex ${CMAKE_MATCH_2}) 2239 | list (LENGTH _sourceFiles _numberOfSources) 2240 | if (NOT _startIndex LESS _numberOfSources) 2241 | math (EXPR _startIndex "${_numberOfSources} - 1") 2242 | endif() 2243 | if (NOT _endIndex LESS _numberOfSources) 2244 | math (EXPR _endIndex "${_numberOfSources} - 1") 2245 | endif() 2246 | set (_files "") 2247 | foreach (_index RANGE ${_startIndex} ${_endIndex}) 2248 | list (GET _sourceFiles ${_index} _file) 2249 | list (APPEND _files "${_file}") 2250 | endforeach() 2251 | else() 2252 | set (_files ${_sourceFiles}) 2253 | endif() 2254 | set (${_sourcesVar} ${_files} PARENT_SCOPE) 2255 | endfunction() 2256 | 2257 | function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) 2258 | set (_dependencySources "") 2259 | # depend on target's generated source files 2260 | get_target_property(_targetSourceFiles ${_target} SOURCES) 2261 | cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) 2262 | if (_generatedSources) 2263 | # but omit all generated source files that have the COTIRE_EXCLUDED property set to true 2264 | cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) 2265 | if (_excludedGeneratedSources) 2266 | list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) 2267 | endif() 2268 | # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly 2269 | cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) 2270 | if (_excludedNonDependencySources) 2271 | list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) 2272 | endif() 2273 | if (_generatedSources) 2274 | list (APPEND _dependencySources ${_generatedSources}) 2275 | endif() 2276 | endif() 2277 | if (COTIRE_DEBUG AND _dependencySources) 2278 | message (STATUS "${_language} ${_target} unity source dependencies: ${_dependencySources}") 2279 | endif() 2280 | set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) 2281 | endfunction() 2282 | 2283 | function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) 2284 | set (_dependencySources "") 2285 | # depend on target source files marked with custom COTIRE_DEPENDENCY property 2286 | get_target_property(_targetSourceFiles ${_target} SOURCES) 2287 | cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles}) 2288 | if (COTIRE_DEBUG AND _dependencySources) 2289 | message (STATUS "${_language} ${_target} prefix header dependencies: ${_dependencySources}") 2290 | endif() 2291 | set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) 2292 | endfunction() 2293 | 2294 | function (cotire_generate_target_script _language _configurations _target _targetScriptVar _targetConfigScriptVar) 2295 | set (_targetSources ${ARGN}) 2296 | cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${_targetSources}) 2297 | cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${_targetSources}) 2298 | # set up variables to be configured 2299 | set (COTIRE_TARGET_LANGUAGE "${_language}") 2300 | get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) 2301 | cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) 2302 | get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) 2303 | cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) 2304 | get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) 2305 | get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) 2306 | get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) 2307 | get_target_property(COTIRE_TARGET_INCLUDE_PRIORITY_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH) 2308 | cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${_targetSources}) 2309 | cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${_targetSources}) 2310 | set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") 2311 | foreach (_config ${_configurations}) 2312 | string (TOUPPER "${_config}" _upperConfig) 2313 | cotire_get_target_include_directories( 2314 | "${_config}" "${_language}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}) 2315 | cotire_get_target_compile_definitions( 2316 | "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) 2317 | cotire_get_target_compiler_flags( 2318 | "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) 2319 | cotire_get_source_files_compile_definitions( 2320 | "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${_targetSources}) 2321 | endforeach() 2322 | get_target_property(COTIRE_TARGET_${_language}_COMPILER_LAUNCHER ${_target} ${_language}_COMPILER_LAUNCHER) 2323 | # set up COTIRE_TARGET_SOURCES 2324 | set (COTIRE_TARGET_SOURCES "") 2325 | foreach (_sourceFile ${_targetSources}) 2326 | get_source_file_property(_generated "${_sourceFile}" GENERATED) 2327 | if (_generated) 2328 | # use absolute paths for generated files only, retrieving the LOCATION property is an expensive operation 2329 | get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) 2330 | list (APPEND COTIRE_TARGET_SOURCES "${_sourceLocation}") 2331 | else() 2332 | list (APPEND COTIRE_TARGET_SOURCES "${_sourceFile}") 2333 | endif() 2334 | endforeach() 2335 | # copy variable definitions to cotire target script 2336 | get_cmake_property(_vars VARIABLES) 2337 | string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") 2338 | # omit COTIRE_*_INIT variables 2339 | string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+_INIT" _initVars "${_matchVars}") 2340 | if (_initVars) 2341 | list (REMOVE_ITEM _matchVars ${_initVars}) 2342 | endif() 2343 | # omit COTIRE_VERBOSE which is passed as a CMake define on command line 2344 | list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) 2345 | set (_contents "") 2346 | set (_contentsHasGeneratorExpressions FALSE) 2347 | foreach (_var IN LISTS _matchVars ITEMS 2348 | XCODE MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES 2349 | CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER_VERSION 2350 | CMAKE_${_language}_COMPILER_LAUNCHER CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 2351 | CMAKE_INCLUDE_FLAG_${_language} CMAKE_INCLUDE_FLAG_SEP_${_language} 2352 | CMAKE_INCLUDE_SYSTEM_FLAG_${_language} 2353 | CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG 2354 | CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG 2355 | CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) 2356 | if (DEFINED ${_var}) 2357 | string (REPLACE "\"" "\\\"" _value "${${_var}}") 2358 | set (_contents "${_contents}set (${_var} \"${_value}\")\n") 2359 | if (NOT _contentsHasGeneratorExpressions) 2360 | if ("${_value}" MATCHES "\\$<.*>") 2361 | set (_contentsHasGeneratorExpressions TRUE) 2362 | endif() 2363 | endif() 2364 | endif() 2365 | endforeach() 2366 | # generate target script file 2367 | get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) 2368 | set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") 2369 | cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) 2370 | if (_contentsHasGeneratorExpressions) 2371 | # use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time 2372 | set (_configNameOrNoneGeneratorExpression "$<$:None>$<$>:$>") 2373 | set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}") 2374 | file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}") 2375 | else() 2376 | set (_targetCotireConfigScript "${_targetCotireScript}") 2377 | endif() 2378 | set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) 2379 | set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE) 2380 | endfunction() 2381 | 2382 | function (cotire_setup_pch_file_compilation _language _target _targetScript _prefixFile _pchFile _hostFile) 2383 | set (_sourceFiles ${ARGN}) 2384 | if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR 2385 | (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) 2386 | # for MSVC, Intel and Clang-cl, we attach the precompiled header compilation to the host file 2387 | # the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion 2388 | if (_sourceFiles) 2389 | set (_flags "") 2390 | cotire_add_pch_compilation_flags( 2391 | "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" 2392 | "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) 2393 | set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") 2394 | set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") 2395 | # make object file generated from host file depend on prefix header 2396 | set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") 2397 | # mark host file as cotired to prevent it from being used in another cotired target 2398 | set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}") 2399 | endif() 2400 | elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") 2401 | # for makefile based generator, we add a custom command to precompile the prefix header 2402 | if (_targetScript) 2403 | cotire_set_cmd_to_prologue(_cmds) 2404 | list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") 2405 | if (MSVC_IDE) 2406 | file (TO_NATIVE_PATH "${_pchFile}" _pchFileLogPath) 2407 | else() 2408 | file (RELATIVE_PATH _pchFileLogPath "${CMAKE_BINARY_DIR}" "${_pchFile}") 2409 | endif() 2410 | # make precompiled header compilation depend on the actual compiler executable used to force 2411 | # re-compilation when the compiler executable is updated. This prevents "created by a different GCC executable" 2412 | # warnings when the precompiled header is included. 2413 | get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) 2414 | if (COTIRE_DEBUG) 2415 | message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} ${_realCompilerExe} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") 2416 | endif() 2417 | set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) 2418 | add_custom_command( 2419 | OUTPUT "${_pchFile}" 2420 | COMMAND ${_cmds} 2421 | DEPENDS "${_prefixFile}" "${_realCompilerExe}" 2422 | IMPLICIT_DEPENDS ${_language} "${_prefixFile}" 2423 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 2424 | COMMENT "Building ${_language} precompiled header ${_pchFileLogPath}" 2425 | VERBATIM) 2426 | endif() 2427 | endif() 2428 | endfunction() 2429 | 2430 | function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile _hostFile) 2431 | if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR 2432 | (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) 2433 | # for MSVC, Intel and clang-cl, we include the precompiled header in all but the host file 2434 | # the host file does the precompiled header compilation, see cotire_setup_pch_file_compilation 2435 | set (_sourceFiles ${ARGN}) 2436 | list (LENGTH _sourceFiles _numberOfSourceFiles) 2437 | if (_numberOfSourceFiles GREATER 0) 2438 | # mark sources as cotired to prevent them from being used in another cotired target 2439 | set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") 2440 | set (_flags "") 2441 | cotire_add_prefix_pch_inclusion_flags( 2442 | "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" 2443 | "${_prefixFile}" "${_pchFile}" _flags) 2444 | set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") 2445 | # make object files generated from source files depend on precompiled header 2446 | set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") 2447 | endif() 2448 | elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") 2449 | set (_sourceFiles ${_hostFile} ${ARGN}) 2450 | if (NOT _wholeTarget) 2451 | # for makefile based generator, we force the inclusion of the prefix header for a subset 2452 | # of the source files, if this is a multi-language target or has excluded files 2453 | set (_flags "") 2454 | cotire_add_prefix_pch_inclusion_flags( 2455 | "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" 2456 | "${_prefixFile}" "${_pchFile}" _flags) 2457 | set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") 2458 | # mark sources as cotired to prevent them from being used in another cotired target 2459 | set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") 2460 | endif() 2461 | # make object files generated from source files depend on precompiled header 2462 | set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") 2463 | endif() 2464 | endfunction() 2465 | 2466 | function (cotire_setup_prefix_file_inclusion _language _target _prefixFile) 2467 | set (_sourceFiles ${ARGN}) 2468 | # force the inclusion of the prefix header for the given source files 2469 | set (_flags "") 2470 | set (_pchFile "") 2471 | cotire_add_prefix_pch_inclusion_flags( 2472 | "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" 2473 | "${_prefixFile}" "${_pchFile}" _flags) 2474 | set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") 2475 | # mark sources as cotired to prevent them from being used in another cotired target 2476 | set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") 2477 | # make object files generated from source files depend on prefix header 2478 | set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") 2479 | endfunction() 2480 | 2481 | function (cotire_get_first_set_property_value _propertyValueVar _type _object) 2482 | set (_properties ${ARGN}) 2483 | foreach (_property ${_properties}) 2484 | get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) 2485 | if (_propertyValue) 2486 | set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) 2487 | return() 2488 | endif() 2489 | endforeach() 2490 | set (${_propertyValueVar} "" PARENT_SCOPE) 2491 | endfunction() 2492 | 2493 | function (cotire_setup_combine_command _language _targetScript _joinedFile _cmdsVar) 2494 | set (_files ${ARGN}) 2495 | set (_filesPaths "") 2496 | foreach (_file ${_files}) 2497 | get_filename_component(_filePath "${_file}" ABSOLUTE) 2498 | list (APPEND _filesPaths "${_filePath}") 2499 | endforeach() 2500 | cotire_set_cmd_to_prologue(_prefixCmd) 2501 | list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine") 2502 | if (_targetScript) 2503 | list (APPEND _prefixCmd "${_targetScript}") 2504 | endif() 2505 | list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths}) 2506 | if (COTIRE_DEBUG) 2507 | message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") 2508 | endif() 2509 | set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) 2510 | if (MSVC_IDE) 2511 | file (TO_NATIVE_PATH "${_joinedFile}" _joinedFileLogPath) 2512 | else() 2513 | file (RELATIVE_PATH _joinedFileLogPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") 2514 | endif() 2515 | get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE) 2516 | get_filename_component(_joinedFileExt "${_joinedFile}" EXT) 2517 | if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$") 2518 | set (_comment "Generating ${_language} unity source ${_joinedFileLogPath}") 2519 | elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$") 2520 | if (_joinedFileExt MATCHES "^\\.c") 2521 | set (_comment "Generating ${_language} prefix source ${_joinedFileLogPath}") 2522 | else() 2523 | set (_comment "Generating ${_language} prefix header ${_joinedFileLogPath}") 2524 | endif() 2525 | else() 2526 | set (_comment "Generating ${_joinedFileLogPath}") 2527 | endif() 2528 | add_custom_command( 2529 | OUTPUT "${_joinedFile}" 2530 | COMMAND ${_prefixCmd} 2531 | DEPENDS ${_files} 2532 | COMMENT "${_comment}" 2533 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 2534 | VERBATIM) 2535 | list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) 2536 | set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) 2537 | endfunction() 2538 | 2539 | function (cotire_setup_target_pch_usage _languages _target _wholeTarget) 2540 | if (XCODE) 2541 | # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers 2542 | set (_prefixFiles "") 2543 | foreach (_language ${_languages}) 2544 | get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) 2545 | if (_prefixFile) 2546 | list (APPEND _prefixFiles "${_prefixFile}") 2547 | endif() 2548 | endforeach() 2549 | set (_cmds ${ARGN}) 2550 | list (LENGTH _prefixFiles _numberOfPrefixFiles) 2551 | if (_numberOfPrefixFiles GREATER 1) 2552 | # we also generate a generic, single prefix header which includes all language specific prefix headers 2553 | set (_language "") 2554 | set (_targetScript "") 2555 | cotire_make_prefix_file_path("${_language}" ${_target} _prefixHeader) 2556 | cotire_setup_combine_command("${_language}" "${_targetScript}" "${_prefixHeader}" _cmds ${_prefixFiles}) 2557 | else() 2558 | set (_prefixHeader "${_prefixFiles}") 2559 | endif() 2560 | if (COTIRE_DEBUG) 2561 | message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") 2562 | endif() 2563 | # because CMake PRE_BUILD command does not support dependencies, 2564 | # we check dependencies explicity in cotire script mode when the pre-build action is run 2565 | add_custom_command( 2566 | TARGET "${_target}" 2567 | PRE_BUILD ${_cmds} 2568 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 2569 | COMMENT "Updating target ${_target} prefix headers" 2570 | VERBATIM) 2571 | # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ 2572 | set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") 2573 | set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") 2574 | elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") 2575 | # for makefile based generator, we force inclusion of the prefix header for all target source files 2576 | # if this is a single-language target without any excluded files 2577 | if (_wholeTarget) 2578 | set (_language "${_languages}") 2579 | # for MSVC, Intel and clang-cl, precompiled header inclusion is always done on the source file level 2580 | # see cotire_setup_pch_file_inclusion 2581 | if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT 2582 | (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) 2583 | get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) 2584 | if (_prefixFile) 2585 | get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) 2586 | set (_options COMPILE_OPTIONS) 2587 | cotire_add_prefix_pch_inclusion_flags( 2588 | "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" 2589 | "${_prefixFile}" "${_pchFile}" _options) 2590 | set_property(TARGET ${_target} APPEND PROPERTY ${_options}) 2591 | endif() 2592 | endif() 2593 | endif() 2594 | endif() 2595 | endfunction() 2596 | 2597 | function (cotire_setup_unity_generation_commands _language _target _targetScript _targetConfigScript _unityFiles _cmdsVar) 2598 | set (_dependencySources "") 2599 | cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) 2600 | foreach (_unityFile ${_unityFiles}) 2601 | set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) 2602 | # set up compiled unity source dependencies via OBJECT_DEPENDS 2603 | # this ensures that missing source files are generated before the unity file is compiled 2604 | if (COTIRE_DEBUG AND _dependencySources) 2605 | message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}") 2606 | endif() 2607 | if (_dependencySources) 2608 | # the OBJECT_DEPENDS property requires a list of full paths 2609 | set (_objectDependsPaths "") 2610 | foreach (_sourceFile ${_dependencySources}) 2611 | get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) 2612 | list (APPEND _objectDependsPaths "${_sourceLocation}") 2613 | endforeach() 2614 | set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_objectDependsPaths}) 2615 | endif() 2616 | if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") 2617 | # unity file compilation results in potentially huge object file, 2618 | # thus use /bigobj by default unter cl.exe and Windows Intel 2619 | set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj") 2620 | endif() 2621 | cotire_set_cmd_to_prologue(_unityCmd) 2622 | list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}") 2623 | if (CMAKE_VERSION VERSION_LESS "3.1.0") 2624 | set (_unityCmdDepends "${_targetScript}") 2625 | else() 2626 | # CMake 3.1.0 supports generator expressions in arguments to DEPENDS 2627 | set (_unityCmdDepends "${_targetConfigScript}") 2628 | endif() 2629 | if (MSVC_IDE) 2630 | file (TO_NATIVE_PATH "${_unityFile}" _unityFileLogPath) 2631 | else() 2632 | file (RELATIVE_PATH _unityFileLogPath "${CMAKE_BINARY_DIR}" "${_unityFile}") 2633 | endif() 2634 | if (COTIRE_DEBUG) 2635 | message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_unityCmdDepends}") 2636 | endif() 2637 | add_custom_command( 2638 | OUTPUT "${_unityFile}" 2639 | COMMAND ${_unityCmd} 2640 | DEPENDS ${_unityCmdDepends} 2641 | COMMENT "Generating ${_language} unity source ${_unityFileLogPath}" 2642 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 2643 | VERBATIM) 2644 | list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) 2645 | endforeach() 2646 | set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) 2647 | endfunction() 2648 | 2649 | function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) 2650 | set (_sourceFiles ${ARGN}) 2651 | set (_dependencySources "") 2652 | cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) 2653 | cotire_set_cmd_to_prologue(_prefixCmd) 2654 | list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" ${_unityFiles}) 2655 | set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) 2656 | # make prefix header generation depend on the actual compiler executable used to force 2657 | # re-generation when the compiler executable is updated. This prevents "file not found" 2658 | # errors for compiler version specific system header files. 2659 | get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) 2660 | if (COTIRE_DEBUG) 2661 | message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources} ${_realCompilerExe}") 2662 | endif() 2663 | if (MSVC_IDE) 2664 | file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileLogPath) 2665 | else() 2666 | file (RELATIVE_PATH _prefixFileLogPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") 2667 | endif() 2668 | get_filename_component(_prefixFileExt "${_prefixFile}" EXT) 2669 | if (_prefixFileExt MATCHES "^\\.c") 2670 | set (_comment "Generating ${_language} prefix source ${_prefixFileLogPath}") 2671 | else() 2672 | set (_comment "Generating ${_language} prefix header ${_prefixFileLogPath}") 2673 | endif() 2674 | # prevent pre-processing errors upon generating the prefix header when a target's generated include file does not yet exist 2675 | # we do not add a file-level dependency for the target's generated files though, because we only want to depend on their existence 2676 | # thus we make the prefix header generation depend on a custom helper target which triggers the generation of the files 2677 | set (_preTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}_pre") 2678 | if (TARGET ${_preTargetName}) 2679 | # custom helper target has already been generated while processing a different language 2680 | list (APPEND _dependencySources ${_preTargetName}) 2681 | else() 2682 | get_target_property(_targetSourceFiles ${_target} SOURCES) 2683 | cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) 2684 | if (_generatedSources) 2685 | add_custom_target("${_preTargetName}" DEPENDS ${_generatedSources}) 2686 | cotire_init_target("${_preTargetName}") 2687 | list (APPEND _dependencySources ${_preTargetName}) 2688 | endif() 2689 | endif() 2690 | add_custom_command( 2691 | OUTPUT "${_prefixFile}" "${_prefixFile}.log" 2692 | COMMAND ${_prefixCmd} 2693 | DEPENDS ${_unityFiles} ${_dependencySources} "${_realCompilerExe}" 2694 | COMMENT "${_comment}" 2695 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 2696 | VERBATIM) 2697 | list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) 2698 | set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) 2699 | endfunction() 2700 | 2701 | function (cotire_setup_prefix_generation_from_unity_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) 2702 | set (_sourceFiles ${ARGN}) 2703 | if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") 2704 | # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma 2705 | cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) 2706 | else() 2707 | set (_prefixSourceFile "${_prefixFile}") 2708 | endif() 2709 | cotire_setup_prefix_generation_command( 2710 | ${_language} ${_target} "${_targetScript}" 2711 | "${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles}) 2712 | if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") 2713 | # set up generation of a prefix source file which includes the prefix header 2714 | cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) 2715 | endif() 2716 | set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) 2717 | endfunction() 2718 | 2719 | function (cotire_setup_prefix_generation_from_provided_command _language _target _targetScript _prefixFile _cmdsVar) 2720 | set (_prefixHeaderFiles ${ARGN}) 2721 | if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") 2722 | # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma 2723 | cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) 2724 | else() 2725 | set (_prefixSourceFile "${_prefixFile}") 2726 | endif() 2727 | cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles}) 2728 | if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") 2729 | # set up generation of a prefix source file which includes the prefix header 2730 | cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) 2731 | endif() 2732 | set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) 2733 | endfunction() 2734 | 2735 | function (cotire_init_cotire_target_properties _target) 2736 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) 2737 | if (NOT _isSet) 2738 | set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) 2739 | endif() 2740 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) 2741 | if (NOT _isSet) 2742 | set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) 2743 | endif() 2744 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) 2745 | if (NOT _isSet) 2746 | set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) 2747 | endif() 2748 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) 2749 | if (NOT _isSet) 2750 | set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") 2751 | cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") 2752 | if (NOT _isRelative) 2753 | set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") 2754 | endif() 2755 | endif() 2756 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) 2757 | if (NOT _isSet) 2758 | set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") 2759 | endif() 2760 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH SET) 2761 | if (NOT _isSet) 2762 | set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "") 2763 | endif() 2764 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) 2765 | if (NOT _isSet) 2766 | set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") 2767 | endif() 2768 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) 2769 | if (NOT _isSet) 2770 | set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") 2771 | endif() 2772 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET) 2773 | if (NOT _isSet) 2774 | set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY_UNITY") 2775 | endif() 2776 | get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) 2777 | if (NOT _isSet) 2778 | if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) 2779 | set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") 2780 | else() 2781 | set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") 2782 | endif() 2783 | endif() 2784 | endfunction() 2785 | 2786 | function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) 2787 | get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) 2788 | get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) 2789 | string (REPLACE ";" " " _languagesStr "${_languages}") 2790 | math (EXPR _numberOfExcludedFiles "${ARGC} - 4") 2791 | if (_numberOfExcludedFiles EQUAL 0) 2792 | set (_excludedStr "") 2793 | elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4) 2794 | string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}") 2795 | else() 2796 | set (_excludedStr "excluding ${_numberOfExcludedFiles} files") 2797 | endif() 2798 | set (_targetMsg "") 2799 | if (NOT _languages) 2800 | set (_targetMsg "Target ${_target} cannot be cotired.") 2801 | if (_disableMsg) 2802 | set (_targetMsg "${_targetMsg} ${_disableMsg}") 2803 | endif() 2804 | elseif (NOT _targetUsePCH AND NOT _targetAddSCU) 2805 | set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") 2806 | if (_disableMsg) 2807 | set (_targetMsg "${_targetMsg} ${_disableMsg}") 2808 | endif() 2809 | elseif (NOT _targetUsePCH) 2810 | if (_excludedStr) 2811 | set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.") 2812 | else() 2813 | set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") 2814 | endif() 2815 | if (_disableMsg) 2816 | set (_targetMsg "${_targetMsg} ${_disableMsg}") 2817 | endif() 2818 | elseif (NOT _targetAddSCU) 2819 | if (_excludedStr) 2820 | set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.") 2821 | else() 2822 | set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") 2823 | endif() 2824 | if (_disableMsg) 2825 | set (_targetMsg "${_targetMsg} ${_disableMsg}") 2826 | endif() 2827 | else() 2828 | if (_excludedStr) 2829 | set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.") 2830 | else() 2831 | set (_targetMsg "${_languagesStr} target ${_target} cotired.") 2832 | endif() 2833 | endif() 2834 | set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) 2835 | endfunction() 2836 | 2837 | function (cotire_choose_target_languages _target _targetLanguagesVar _wholeTargetVar) 2838 | set (_languages ${ARGN}) 2839 | set (_allSourceFiles "") 2840 | set (_allExcludedSourceFiles "") 2841 | set (_allCotiredSourceFiles "") 2842 | set (_targetLanguages "") 2843 | set (_pchEligibleTargetLanguages "") 2844 | get_target_property(_targetType ${_target} TYPE) 2845 | get_target_property(_targetSourceFiles ${_target} SOURCES) 2846 | get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) 2847 | get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) 2848 | set (_disableMsg "") 2849 | foreach (_language ${_languages}) 2850 | get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) 2851 | get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) 2852 | if (_prefixHeader OR _unityBuildFile) 2853 | message (STATUS "cotire: target ${_target} has already been cotired.") 2854 | set (${_targetLanguagesVar} "" PARENT_SCOPE) 2855 | return() 2856 | endif() 2857 | if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$" AND DEFINED CMAKE_${_language}_COMPILER_ID) 2858 | if (CMAKE_${_language}_COMPILER_ID) 2859 | cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg) 2860 | if (_disableMsg) 2861 | set (_targetUsePCH FALSE) 2862 | endif() 2863 | endif() 2864 | endif() 2865 | set (_sourceFiles "") 2866 | set (_excludedSources "") 2867 | set (_cotiredSources "") 2868 | cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) 2869 | if (_sourceFiles OR _excludedSources OR _cotiredSources) 2870 | list (APPEND _targetLanguages ${_language}) 2871 | endif() 2872 | if (_sourceFiles) 2873 | list (APPEND _allSourceFiles ${_sourceFiles}) 2874 | endif() 2875 | list (LENGTH _sourceFiles _numberOfSources) 2876 | if (NOT _numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) 2877 | list (APPEND _pchEligibleTargetLanguages ${_language}) 2878 | endif() 2879 | if (_excludedSources) 2880 | list (APPEND _allExcludedSourceFiles ${_excludedSources}) 2881 | endif() 2882 | if (_cotiredSources) 2883 | list (APPEND _allCotiredSourceFiles ${_cotiredSources}) 2884 | endif() 2885 | endforeach() 2886 | set (_targetMsgLevel STATUS) 2887 | if (NOT _targetLanguages) 2888 | string (REPLACE ";" " or " _languagesStr "${_languages}") 2889 | set (_disableMsg "No ${_languagesStr} source files.") 2890 | set (_targetUsePCH FALSE) 2891 | set (_targetAddSCU FALSE) 2892 | endif() 2893 | if (_targetUsePCH) 2894 | if (_allCotiredSourceFiles) 2895 | cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) 2896 | list (REMOVE_DUPLICATES _cotireTargets) 2897 | string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") 2898 | set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") 2899 | set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") 2900 | set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") 2901 | set (_targetMsgLevel SEND_ERROR) 2902 | set (_targetUsePCH FALSE) 2903 | elseif (NOT _pchEligibleTargetLanguages) 2904 | set (_disableMsg "Too few applicable sources.") 2905 | set (_targetUsePCH FALSE) 2906 | elseif (XCODE AND _allExcludedSourceFiles) 2907 | # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target 2908 | set (_disableMsg "Exclusion of source files not supported for generator Xcode.") 2909 | set (_targetUsePCH FALSE) 2910 | elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") 2911 | # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target 2912 | set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") 2913 | set (_targetUsePCH FALSE) 2914 | endif() 2915 | endif() 2916 | if (_targetAddSCU) 2917 | # disable unity builds if automatic Qt processing is used 2918 | get_target_property(_targetAutoMoc ${_target} AUTOMOC) 2919 | get_target_property(_targetAutoUic ${_target} AUTOUIC) 2920 | get_target_property(_targetAutoRcc ${_target} AUTORCC) 2921 | if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) 2922 | if (_disableMsg) 2923 | set (_disableMsg "${_disableMsg} Target uses automatic CMake Qt processing.") 2924 | else() 2925 | set (_disableMsg "Target uses automatic CMake Qt processing.") 2926 | endif() 2927 | set (_targetAddSCU FALSE) 2928 | endif() 2929 | endif() 2930 | set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) 2931 | set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) 2932 | cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) 2933 | if (_targetMsg) 2934 | if (NOT DEFINED COTIREMSG_${_target}) 2935 | set (COTIREMSG_${_target} "") 2936 | endif() 2937 | if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR 2938 | NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") 2939 | # cache message to avoid redundant messages on re-configure 2940 | set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") 2941 | message (${_targetMsgLevel} "${_targetMsg}") 2942 | endif() 2943 | endif() 2944 | list (LENGTH _targetLanguages _numberOfLanguages) 2945 | if (_numberOfLanguages GREATER 1 OR _allExcludedSourceFiles) 2946 | set (${_wholeTargetVar} FALSE PARENT_SCOPE) 2947 | else() 2948 | set (${_wholeTargetVar} TRUE PARENT_SCOPE) 2949 | endif() 2950 | set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) 2951 | endfunction() 2952 | 2953 | function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar) 2954 | set (_sourceFiles ${ARGN}) 2955 | get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) 2956 | if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)") 2957 | if (DEFINED CMAKE_MATCH_2) 2958 | set (_numberOfThreads "${CMAKE_MATCH_2}") 2959 | else() 2960 | set (_numberOfThreads "") 2961 | endif() 2962 | if (NOT _numberOfThreads) 2963 | # use all available cores 2964 | ProcessorCount(_numberOfThreads) 2965 | endif() 2966 | list (LENGTH _sourceFiles _numberOfSources) 2967 | math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}") 2968 | elseif (NOT _maxIncludes MATCHES "[0-9]+") 2969 | set (_maxIncludes 0) 2970 | endif() 2971 | if (COTIRE_DEBUG) 2972 | message (STATUS "${_target} unity source max includes: ${_maxIncludes}") 2973 | endif() 2974 | set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE) 2975 | endfunction() 2976 | 2977 | function (cotire_process_target_language _language _configurations _target _wholeTarget _cmdsVar) 2978 | set (${_cmdsVar} "" PARENT_SCOPE) 2979 | get_target_property(_targetSourceFiles ${_target} SOURCES) 2980 | set (_sourceFiles "") 2981 | set (_excludedSources "") 2982 | set (_cotiredSources "") 2983 | cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) 2984 | if (NOT _sourceFiles AND NOT _cotiredSources) 2985 | return() 2986 | endif() 2987 | set (_cmds "") 2988 | # check for user provided unity source file list 2989 | get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT) 2990 | if (NOT _unitySourceFiles) 2991 | set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources}) 2992 | endif() 2993 | cotire_generate_target_script( 2994 | ${_language} "${_configurations}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles}) 2995 | # set up unity files for parallel compilation 2996 | cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles}) 2997 | cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles}) 2998 | list (LENGTH _unityFiles _numberOfUnityFiles) 2999 | if (_numberOfUnityFiles EQUAL 0) 3000 | return() 3001 | elseif (_numberOfUnityFiles GREATER 1) 3002 | cotire_setup_unity_generation_commands( 3003 | ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles}) 3004 | endif() 3005 | # set up single unity file for prefix header generation 3006 | cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) 3007 | cotire_setup_unity_generation_commands( 3008 | ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFile}" _cmds ${_unitySourceFiles}) 3009 | cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) 3010 | # set up prefix header 3011 | if (_prefixFile) 3012 | # check for user provided prefix header files 3013 | get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) 3014 | if (_prefixHeaderFiles) 3015 | cotire_setup_prefix_generation_from_provided_command( 3016 | ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles}) 3017 | else() 3018 | cotire_setup_prefix_generation_from_unity_command( 3019 | ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_unityFile}" _cmds ${_unitySourceFiles}) 3020 | endif() 3021 | # check if selected language has enough sources at all 3022 | list (LENGTH _sourceFiles _numberOfSources) 3023 | if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) 3024 | set (_targetUsePCH FALSE) 3025 | else() 3026 | get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) 3027 | endif() 3028 | if (_targetUsePCH) 3029 | cotire_make_pch_file_path(${_language} ${_target} _pchFile) 3030 | if (_pchFile) 3031 | # first file in _sourceFiles is passed as the host file 3032 | cotire_setup_pch_file_compilation( 3033 | ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) 3034 | cotire_setup_pch_file_inclusion( 3035 | ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) 3036 | endif() 3037 | elseif (_prefixHeaderFiles) 3038 | # user provided prefix header must be included unconditionally 3039 | cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_sourceFiles}) 3040 | endif() 3041 | endif() 3042 | # mark target as cotired for language 3043 | set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") 3044 | if (_prefixFile) 3045 | set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") 3046 | if (_targetUsePCH AND _pchFile) 3047 | set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") 3048 | endif() 3049 | endif() 3050 | set (${_cmdsVar} ${_cmds} PARENT_SCOPE) 3051 | endfunction() 3052 | 3053 | function (cotire_setup_clean_target _target) 3054 | set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") 3055 | if (NOT TARGET "${_cleanTargetName}") 3056 | cotire_set_cmd_to_prologue(_cmds) 3057 | get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) 3058 | list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") 3059 | add_custom_target(${_cleanTargetName} 3060 | COMMAND ${_cmds} 3061 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 3062 | COMMENT "Cleaning up target ${_target} cotire generated files" 3063 | VERBATIM) 3064 | cotire_init_target("${_cleanTargetName}") 3065 | endif() 3066 | endfunction() 3067 | 3068 | function (cotire_setup_pch_target _languages _configurations _target) 3069 | if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") 3070 | # for makefile based generators, we add a custom target to trigger the generation of the cotire related files 3071 | set (_dependsFiles "") 3072 | foreach (_language ${_languages}) 3073 | set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) 3074 | if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT 3075 | (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) 3076 | # MSVC, Intel and clang-cl only create precompiled header as a side effect 3077 | list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) 3078 | endif() 3079 | cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) 3080 | if (_dependsFile) 3081 | list (APPEND _dependsFiles "${_dependsFile}") 3082 | endif() 3083 | endforeach() 3084 | if (_dependsFiles) 3085 | set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") 3086 | add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) 3087 | cotire_init_target("${_pchTargetName}") 3088 | cotire_add_to_pch_all_target(${_pchTargetName}) 3089 | endif() 3090 | else() 3091 | # for other generators, we add the "clean all" target to clean up the precompiled header 3092 | cotire_setup_clean_all_target() 3093 | endif() 3094 | endfunction() 3095 | 3096 | function (cotire_filter_object_libraries _target _objectLibrariesVar) 3097 | set (_objectLibraries "") 3098 | foreach (_source ${ARGN}) 3099 | if (_source MATCHES "^\\$$") 3100 | list (APPEND _objectLibraries "${_source}") 3101 | endif() 3102 | endforeach() 3103 | set (${_objectLibrariesVar} ${_objectLibraries} PARENT_SCOPE) 3104 | endfunction() 3105 | 3106 | function (cotire_collect_unity_target_sources _target _languages _unityTargetSourcesVar) 3107 | get_target_property(_targetSourceFiles ${_target} SOURCES) 3108 | set (_unityTargetSources ${_targetSourceFiles}) 3109 | foreach (_language ${_languages}) 3110 | get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) 3111 | if (_unityFiles) 3112 | # remove source files that are included in the unity source 3113 | set (_sourceFiles "") 3114 | set (_excludedSources "") 3115 | set (_cotiredSources "") 3116 | cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) 3117 | if (_sourceFiles OR _cotiredSources) 3118 | list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) 3119 | endif() 3120 | # add unity source files instead 3121 | list (APPEND _unityTargetSources ${_unityFiles}) 3122 | endif() 3123 | endforeach() 3124 | # handle object libraries which are part of the target's sources 3125 | get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) 3126 | if ("${_linkLibrariesStrategy}" MATCHES "^COPY_UNITY$") 3127 | cotire_filter_object_libraries(${_target} _objectLibraries ${_targetSourceFiles}) 3128 | if (_objectLibraries) 3129 | cotire_map_libraries("${_linkLibrariesStrategy}" _unityObjectLibraries ${_objectLibraries}) 3130 | list (REMOVE_ITEM _unityTargetSources ${_objectLibraries}) 3131 | list (APPEND _unityTargetSources ${_unityObjectLibraries}) 3132 | endif() 3133 | endif() 3134 | set (${_unityTargetSourcesVar} ${_unityTargetSources} PARENT_SCOPE) 3135 | endfunction() 3136 | 3137 | function (cotire_setup_unity_target_pch_usage _languages _target) 3138 | foreach (_language ${_languages}) 3139 | get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) 3140 | if (_unityFiles) 3141 | get_property(_userPrefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) 3142 | get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) 3143 | if (_userPrefixFile AND _prefixFile) 3144 | # user provided prefix header must be included unconditionally by unity sources 3145 | cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_unityFiles}) 3146 | endif() 3147 | endif() 3148 | endforeach() 3149 | endfunction() 3150 | 3151 | function (cotire_setup_unity_build_target _languages _configurations _target) 3152 | get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) 3153 | if (NOT _unityTargetName) 3154 | set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") 3155 | endif() 3156 | # determine unity target sub type 3157 | get_target_property(_targetType ${_target} TYPE) 3158 | if ("${_targetType}" STREQUAL "EXECUTABLE") 3159 | set (_unityTargetSubType "") 3160 | elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") 3161 | set (_unityTargetSubType "${CMAKE_MATCH_1}") 3162 | else() 3163 | message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.") 3164 | return() 3165 | endif() 3166 | # determine unity target sources 3167 | set (_unityTargetSources "") 3168 | cotire_collect_unity_target_sources(${_target} "${_languages}" _unityTargetSources) 3169 | # prevent AUTOMOC, AUTOUIC and AUTORCC properties from being set when the unity target is created 3170 | set (CMAKE_AUTOMOC OFF) 3171 | set (CMAKE_AUTOUIC OFF) 3172 | set (CMAKE_AUTORCC OFF) 3173 | if (COTIRE_DEBUG) 3174 | message (STATUS "add target ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") 3175 | endif() 3176 | # generate unity target 3177 | if ("${_targetType}" STREQUAL "EXECUTABLE") 3178 | add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) 3179 | else() 3180 | add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) 3181 | endif() 3182 | # copy output location properties 3183 | set (_outputDirProperties 3184 | ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ 3185 | LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ 3186 | RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) 3187 | if (COTIRE_UNITY_OUTPUT_DIRECTORY) 3188 | set (_setDefaultOutputDir TRUE) 3189 | if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") 3190 | set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") 3191 | else() 3192 | # append relative COTIRE_UNITY_OUTPUT_DIRECTORY to target's actual output directory 3193 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) 3194 | cotire_resolve_config_properties("${_configurations}" _properties ${_outputDirProperties}) 3195 | foreach (_property ${_properties}) 3196 | get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) 3197 | if (_outputDir) 3198 | get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) 3199 | set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}") 3200 | set (_setDefaultOutputDir FALSE) 3201 | endif() 3202 | endforeach() 3203 | if (_setDefaultOutputDir) 3204 | get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) 3205 | endif() 3206 | endif() 3207 | if (_setDefaultOutputDir) 3208 | set_target_properties(${_unityTargetName} PROPERTIES 3209 | ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" 3210 | LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" 3211 | RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") 3212 | endif() 3213 | else() 3214 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3215 | ${_outputDirProperties}) 3216 | endif() 3217 | # copy output name 3218 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3219 | ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ 3220 | LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ 3221 | OUTPUT_NAME OUTPUT_NAME_ 3222 | RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ 3223 | PREFIX _POSTFIX SUFFIX 3224 | IMPORT_PREFIX IMPORT_SUFFIX) 3225 | # copy compile stuff 3226 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3227 | COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ 3228 | COMPILE_FLAGS COMPILE_OPTIONS 3229 | Fortran_FORMAT Fortran_MODULE_DIRECTORY 3230 | INCLUDE_DIRECTORIES 3231 | INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_ 3232 | POSITION_INDEPENDENT_CODE 3233 | C_COMPILER_LAUNCHER CXX_COMPILER_LAUNCHER 3234 | C_INCLUDE_WHAT_YOU_USE CXX_INCLUDE_WHAT_YOU_USE 3235 | C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN 3236 | C_CLANG_TIDY CXX_CLANG_TIDY) 3237 | # copy compile features 3238 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3239 | C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED 3240 | CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED 3241 | COMPILE_FEATURES) 3242 | # copy interface stuff 3243 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3244 | COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN 3245 | COMPATIBLE_INTERFACE_STRING 3246 | INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS 3247 | INTERFACE_INCLUDE_DIRECTORIES INTERFACE_SOURCES 3248 | INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES 3249 | INTERFACE_AUTOUIC_OPTIONS NO_SYSTEM_FROM_IMPORTED) 3250 | # copy link stuff 3251 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3252 | BUILD_WITH_INSTALL_RPATH BUILD_WITH_INSTALL_NAME_DIR 3253 | INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH 3254 | LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED 3255 | LINK_FLAGS LINK_FLAGS_ 3256 | LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ 3257 | LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ 3258 | LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC 3259 | STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ 3260 | NO_SONAME SOVERSION VERSION 3261 | LINK_WHAT_YOU_USE BUILD_RPATH) 3262 | # copy cmake stuff 3263 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3264 | IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) 3265 | # copy Apple platform specific stuff 3266 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3267 | BUNDLE BUNDLE_EXTENSION FRAMEWORK FRAMEWORK_VERSION INSTALL_NAME_DIR 3268 | MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_RPATH 3269 | OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE XCTEST 3270 | IOS_INSTALL_COMBINED XCODE_EXPLICIT_FILE_TYPE XCODE_PRODUCT_TYPE) 3271 | # copy Windows platform specific stuff 3272 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3273 | GNUtoMS 3274 | COMPILE_PDB_NAME COMPILE_PDB_NAME_ 3275 | COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_ 3276 | PDB_NAME PDB_NAME_ PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_ 3277 | VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION 3278 | VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE 3279 | VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK 3280 | VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION 3281 | VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER 3282 | VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION 3283 | VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES 3284 | WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS 3285 | DEPLOYMENT_REMOTE_DIRECTORY VS_CONFIGURATION_TYPE 3286 | VS_SDK_REFERENCES VS_USER_PROPS VS_DEBUGGER_WORKING_DIRECTORY) 3287 | # copy Android platform specific stuff 3288 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3289 | ANDROID_API ANDROID_API_MIN ANDROID_GUI 3290 | ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES 3291 | ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR 3292 | ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES 3293 | ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH 3294 | ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE) 3295 | # copy CUDA platform specific stuff 3296 | cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} 3297 | CUDA_PTX_COMPILATION CUDA_SEPARABLE_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS 3298 | CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED) 3299 | # use output name from original target 3300 | get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) 3301 | if (NOT _targetOutputName) 3302 | set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") 3303 | endif() 3304 | # use export symbol from original target 3305 | cotire_get_target_export_symbol("${_target}" _defineSymbol) 3306 | if (_defineSymbol) 3307 | set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") 3308 | if ("${_targetType}" STREQUAL "EXECUTABLE") 3309 | set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) 3310 | endif() 3311 | endif() 3312 | # enable parallel compilation for MSVC 3313 | if (MSVC AND "${CMAKE_GENERATOR}" MATCHES "Visual Studio") 3314 | list (LENGTH _unityTargetSources _numberOfUnityTargetSources) 3315 | if (_numberOfUnityTargetSources GREATER 1) 3316 | set_property(TARGET ${_unityTargetName} APPEND PROPERTY COMPILE_OPTIONS "/MP") 3317 | endif() 3318 | endif() 3319 | cotire_init_target(${_unityTargetName}) 3320 | cotire_add_to_unity_all_target(${_unityTargetName}) 3321 | set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") 3322 | endfunction(cotire_setup_unity_build_target) 3323 | 3324 | function (cotire_target _target) 3325 | set(_options "") 3326 | set(_oneValueArgs "") 3327 | set(_multiValueArgs LANGUAGES CONFIGURATIONS) 3328 | cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) 3329 | if (NOT _option_LANGUAGES) 3330 | get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) 3331 | endif() 3332 | if (NOT _option_CONFIGURATIONS) 3333 | cotire_get_configuration_types(_option_CONFIGURATIONS) 3334 | endif() 3335 | # check if cotire can be applied to target at all 3336 | cotire_is_target_supported(${_target} _isSupported) 3337 | if (NOT _isSupported) 3338 | get_target_property(_imported ${_target} IMPORTED) 3339 | get_target_property(_targetType ${_target} TYPE) 3340 | if (_imported) 3341 | message (WARNING "cotire: imported ${_targetType} target ${_target} cannot be cotired.") 3342 | else() 3343 | message (STATUS "cotire: ${_targetType} target ${_target} cannot be cotired.") 3344 | endif() 3345 | return() 3346 | endif() 3347 | # resolve alias 3348 | get_target_property(_aliasName ${_target} ALIASED_TARGET) 3349 | if (_aliasName) 3350 | if (COTIRE_DEBUG) 3351 | message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.") 3352 | endif() 3353 | set (_target ${_aliasName}) 3354 | endif() 3355 | # check if target needs to be cotired for build type 3356 | # when using configuration types, the test is performed at build time 3357 | cotire_init_cotire_target_properties(${_target}) 3358 | if (NOT CMAKE_CONFIGURATION_TYPES) 3359 | if (CMAKE_BUILD_TYPE) 3360 | list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) 3361 | else() 3362 | list (FIND _option_CONFIGURATIONS "None" _index) 3363 | endif() 3364 | if (_index EQUAL -1) 3365 | if (COTIRE_DEBUG) 3366 | message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") 3367 | endif() 3368 | return() 3369 | endif() 3370 | endif() 3371 | # when not using configuration types, immediately create cotire intermediate dir 3372 | if (NOT CMAKE_CONFIGURATION_TYPES) 3373 | cotire_get_intermediate_dir(_baseDir) 3374 | file (MAKE_DIRECTORY "${_baseDir}") 3375 | endif() 3376 | # choose languages that apply to the target 3377 | cotire_choose_target_languages("${_target}" _targetLanguages _wholeTarget ${_option_LANGUAGES}) 3378 | if (NOT _targetLanguages) 3379 | return() 3380 | endif() 3381 | set (_cmds "") 3382 | foreach (_language ${_targetLanguages}) 3383 | cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} ${_wholeTarget} _cmd) 3384 | if (_cmd) 3385 | list (APPEND _cmds ${_cmd}) 3386 | endif() 3387 | endforeach() 3388 | get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) 3389 | if (_targetAddSCU) 3390 | cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) 3391 | endif() 3392 | get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) 3393 | if (_targetUsePCH) 3394 | cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds}) 3395 | cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) 3396 | if (_targetAddSCU) 3397 | cotire_setup_unity_target_pch_usage("${_targetLanguages}" ${_target}) 3398 | endif() 3399 | endif() 3400 | get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) 3401 | if (_targetAddCleanTarget) 3402 | cotire_setup_clean_target(${_target}) 3403 | endif() 3404 | endfunction(cotire_target) 3405 | 3406 | function (cotire_map_libraries _strategy _mappedLibrariesVar) 3407 | set (_mappedLibraries "") 3408 | foreach (_library ${ARGN}) 3409 | if (_library MATCHES "^\\$$") 3410 | set (_libraryName "${CMAKE_MATCH_1}") 3411 | set (_linkOnly TRUE) 3412 | set (_objectLibrary FALSE) 3413 | elseif (_library MATCHES "^\\$$") 3414 | set (_libraryName "${CMAKE_MATCH_1}") 3415 | set (_linkOnly FALSE) 3416 | set (_objectLibrary TRUE) 3417 | else() 3418 | set (_libraryName "${_library}") 3419 | set (_linkOnly FALSE) 3420 | set (_objectLibrary FALSE) 3421 | endif() 3422 | if ("${_strategy}" MATCHES "COPY_UNITY") 3423 | cotire_is_target_supported(${_libraryName} _isSupported) 3424 | if (_isSupported) 3425 | # use target's corresponding unity target, if available 3426 | get_target_property(_libraryUnityTargetName ${_libraryName} COTIRE_UNITY_TARGET_NAME) 3427 | if (TARGET "${_libraryUnityTargetName}") 3428 | if (_linkOnly) 3429 | list (APPEND _mappedLibraries "$") 3430 | elseif (_objectLibrary) 3431 | list (APPEND _mappedLibraries "$") 3432 | else() 3433 | list (APPEND _mappedLibraries "${_libraryUnityTargetName}") 3434 | endif() 3435 | else() 3436 | list (APPEND _mappedLibraries "${_library}") 3437 | endif() 3438 | else() 3439 | list (APPEND _mappedLibraries "${_library}") 3440 | endif() 3441 | else() 3442 | list (APPEND _mappedLibraries "${_library}") 3443 | endif() 3444 | endforeach() 3445 | list (REMOVE_DUPLICATES _mappedLibraries) 3446 | set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE) 3447 | endfunction() 3448 | 3449 | function (cotire_target_link_libraries _target) 3450 | cotire_is_target_supported(${_target} _isSupported) 3451 | if (NOT _isSupported) 3452 | return() 3453 | endif() 3454 | get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) 3455 | if (TARGET "${_unityTargetName}") 3456 | get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) 3457 | if (COTIRE_DEBUG) 3458 | message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}") 3459 | endif() 3460 | if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$") 3461 | get_target_property(_linkLibraries ${_target} LINK_LIBRARIES) 3462 | if (_linkLibraries) 3463 | cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_linkLibraries}) 3464 | set_target_properties(${_unityTargetName} PROPERTIES LINK_LIBRARIES "${_unityLinkLibraries}") 3465 | if (COTIRE_DEBUG) 3466 | message (STATUS "unity target ${_unityTargetName} link libraries: ${_unityLinkLibraries}") 3467 | endif() 3468 | endif() 3469 | get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES) 3470 | if (_interfaceLinkLibraries) 3471 | cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkInterfaceLibraries ${_interfaceLinkLibraries}) 3472 | set_target_properties(${_unityTargetName} PROPERTIES INTERFACE_LINK_LIBRARIES "${_unityLinkInterfaceLibraries}") 3473 | if (COTIRE_DEBUG) 3474 | message (STATUS "unity target ${_unityTargetName} interface link libraries: ${_unityLinkInterfaceLibraries}") 3475 | endif() 3476 | endif() 3477 | get_target_property(_manualDependencies ${_target} MANUALLY_ADDED_DEPENDENCIES) 3478 | if (_manualDependencies) 3479 | cotire_map_libraries("${_linkLibrariesStrategy}" _unityManualDependencies ${_manualDependencies}) 3480 | if (_unityManualDependencies) 3481 | add_dependencies("${_unityTargetName}" ${_unityManualDependencies}) 3482 | endif() 3483 | endif() 3484 | endif() 3485 | endif() 3486 | endfunction(cotire_target_link_libraries) 3487 | 3488 | function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) 3489 | if (_targetName) 3490 | file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") 3491 | else() 3492 | file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") 3493 | endif() 3494 | # filter files in intermediate directory 3495 | set (_filesToRemove "") 3496 | foreach (_file ${_cotireFiles}) 3497 | get_filename_component(_dir "${_file}" DIRECTORY) 3498 | get_filename_component(_dirName "${_dir}" NAME) 3499 | if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") 3500 | list (APPEND _filesToRemove "${_file}") 3501 | endif() 3502 | endforeach() 3503 | if (_filesToRemove) 3504 | if (COTIRE_VERBOSE) 3505 | message (STATUS "cleaning up ${_filesToRemove}") 3506 | endif() 3507 | file (REMOVE ${_filesToRemove}) 3508 | endif() 3509 | endfunction() 3510 | 3511 | function (cotire_init_target _targetName) 3512 | if (COTIRE_TARGETS_FOLDER) 3513 | set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") 3514 | endif() 3515 | set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_ALL TRUE) 3516 | if (MSVC_IDE) 3517 | set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) 3518 | endif() 3519 | endfunction() 3520 | 3521 | function (cotire_add_to_pch_all_target _pchTargetName) 3522 | set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") 3523 | if (NOT TARGET "${_targetName}") 3524 | add_custom_target("${_targetName}" 3525 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 3526 | VERBATIM) 3527 | cotire_init_target("${_targetName}") 3528 | endif() 3529 | cotire_setup_clean_all_target() 3530 | add_dependencies(${_targetName} ${_pchTargetName}) 3531 | endfunction() 3532 | 3533 | function (cotire_add_to_unity_all_target _unityTargetName) 3534 | set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") 3535 | if (NOT TARGET "${_targetName}") 3536 | add_custom_target("${_targetName}" 3537 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 3538 | VERBATIM) 3539 | cotire_init_target("${_targetName}") 3540 | endif() 3541 | cotire_setup_clean_all_target() 3542 | add_dependencies(${_targetName} ${_unityTargetName}) 3543 | endfunction() 3544 | 3545 | function (cotire_setup_clean_all_target) 3546 | set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") 3547 | if (NOT TARGET "${_targetName}") 3548 | cotire_set_cmd_to_prologue(_cmds) 3549 | list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") 3550 | add_custom_target(${_targetName} 3551 | COMMAND ${_cmds} 3552 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 3553 | COMMENT "Cleaning up all cotire generated files" 3554 | VERBATIM) 3555 | cotire_init_target("${_targetName}") 3556 | endif() 3557 | endfunction() 3558 | 3559 | function (cotire) 3560 | set(_options "") 3561 | set(_oneValueArgs "") 3562 | set(_multiValueArgs LANGUAGES CONFIGURATIONS) 3563 | cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) 3564 | set (_targets ${_option_UNPARSED_ARGUMENTS}) 3565 | foreach (_target ${_targets}) 3566 | if (TARGET ${_target}) 3567 | cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS}) 3568 | else() 3569 | message (WARNING "cotire: ${_target} is not a target.") 3570 | endif() 3571 | endforeach() 3572 | foreach (_target ${_targets}) 3573 | if (TARGET ${_target}) 3574 | cotire_target_link_libraries(${_target}) 3575 | endif() 3576 | endforeach() 3577 | endfunction() 3578 | 3579 | if (CMAKE_SCRIPT_MODE_FILE) 3580 | 3581 | # cotire is being run in script mode 3582 | # locate -P on command args 3583 | set (COTIRE_ARGC -1) 3584 | foreach (_index RANGE ${CMAKE_ARGC}) 3585 | if (COTIRE_ARGC GREATER -1) 3586 | set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") 3587 | math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") 3588 | elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") 3589 | set (COTIRE_ARGC 0) 3590 | endif() 3591 | endforeach() 3592 | 3593 | # include target script if available 3594 | if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") 3595 | # the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES) 3596 | include("${COTIRE_ARGV2}") 3597 | endif() 3598 | 3599 | if (COTIRE_DEBUG) 3600 | message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") 3601 | endif() 3602 | 3603 | if (NOT COTIRE_BUILD_TYPE) 3604 | set (COTIRE_BUILD_TYPE "None") 3605 | endif() 3606 | string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) 3607 | set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) 3608 | set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}}) 3609 | set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) 3610 | set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) 3611 | # check if target has been cotired for actual build type COTIRE_BUILD_TYPE 3612 | list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) 3613 | if (_index GREATER -1) 3614 | set (_sources ${COTIRE_TARGET_SOURCES}) 3615 | set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) 3616 | else() 3617 | if (COTIRE_DEBUG) 3618 | message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") 3619 | endif() 3620 | set (_sources "") 3621 | set (_sourcesDefinitions "") 3622 | endif() 3623 | set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) 3624 | set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) 3625 | set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) 3626 | set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) 3627 | 3628 | if ("${COTIRE_ARGV1}" STREQUAL "unity") 3629 | 3630 | if (XCODE) 3631 | # executing pre-build action under Xcode, check dependency on target script 3632 | set (_dependsOption DEPENDS "${COTIRE_ARGV2}") 3633 | else() 3634 | # executing custom command, no need to re-check for dependencies 3635 | set (_dependsOption "") 3636 | endif() 3637 | 3638 | cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) 3639 | 3640 | cotire_generate_unity_source( 3641 | "${COTIRE_ARGV3}" ${_sources} 3642 | LANGUAGE "${COTIRE_TARGET_LANGUAGE}" 3643 | SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} 3644 | PRE_UNDEFS ${_targetPreUndefs} 3645 | POST_UNDEFS ${_targetPostUndefs} 3646 | SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} 3647 | SOURCES_POST_UNDEFS ${_sourcesPostUndefs} 3648 | ${_dependsOption}) 3649 | 3650 | elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") 3651 | 3652 | if (XCODE) 3653 | # executing pre-build action under Xcode, check dependency on unity file and prefix dependencies 3654 | set (_dependsOption DEPENDS "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS}) 3655 | else() 3656 | # executing custom command, no need to re-check for dependencies 3657 | set (_dependsOption "") 3658 | endif() 3659 | 3660 | set (_files "") 3661 | foreach (_index RANGE 4 ${COTIRE_ARGC}) 3662 | if (COTIRE_ARGV${_index}) 3663 | list (APPEND _files "${COTIRE_ARGV${_index}}") 3664 | endif() 3665 | endforeach() 3666 | 3667 | cotire_generate_prefix_header( 3668 | "${COTIRE_ARGV3}" ${_files} 3669 | COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" 3670 | COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" 3671 | COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} 3672 | COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" 3673 | COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" 3674 | LANGUAGE "${COTIRE_TARGET_LANGUAGE}" 3675 | IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" 3676 | INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH} 3677 | IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" 3678 | INCLUDE_PRIORITY_PATH ${COTIRE_TARGET_INCLUDE_PRIORITY_PATH} 3679 | INCLUDE_DIRECTORIES ${_includeDirs} 3680 | SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} 3681 | COMPILE_DEFINITIONS ${_compileDefinitions} 3682 | COMPILE_FLAGS ${_compileFlags} 3683 | ${_dependsOption}) 3684 | 3685 | elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") 3686 | 3687 | set (_files "") 3688 | foreach (_index RANGE 5 ${COTIRE_ARGC}) 3689 | if (COTIRE_ARGV${_index}) 3690 | list (APPEND _files "${COTIRE_ARGV${_index}}") 3691 | endif() 3692 | endforeach() 3693 | 3694 | cotire_precompile_prefix_header( 3695 | "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" 3696 | COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" 3697 | COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" 3698 | COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} 3699 | COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" 3700 | COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" 3701 | LANGUAGE "${COTIRE_TARGET_LANGUAGE}" 3702 | INCLUDE_DIRECTORIES ${_includeDirs} 3703 | SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} 3704 | COMPILE_DEFINITIONS ${_compileDefinitions} 3705 | COMPILE_FLAGS ${_compileFlags}) 3706 | 3707 | elseif ("${COTIRE_ARGV1}" STREQUAL "combine") 3708 | 3709 | if (COTIRE_TARGET_LANGUAGE) 3710 | set (_combinedFile "${COTIRE_ARGV3}") 3711 | set (_startIndex 4) 3712 | else() 3713 | set (_combinedFile "${COTIRE_ARGV2}") 3714 | set (_startIndex 3) 3715 | endif() 3716 | set (_files "") 3717 | foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC}) 3718 | if (COTIRE_ARGV${_index}) 3719 | list (APPEND _files "${COTIRE_ARGV${_index}}") 3720 | endif() 3721 | endforeach() 3722 | 3723 | if (XCODE) 3724 | # executing pre-build action under Xcode, check dependency on files to be combined 3725 | set (_dependsOption DEPENDS ${_files}) 3726 | else() 3727 | # executing custom command, no need to re-check for dependencies 3728 | set (_dependsOption "") 3729 | endif() 3730 | 3731 | if (COTIRE_TARGET_LANGUAGE) 3732 | cotire_generate_unity_source( 3733 | "${_combinedFile}" ${_files} 3734 | LANGUAGE "${COTIRE_TARGET_LANGUAGE}" 3735 | ${_dependsOption}) 3736 | else() 3737 | cotire_generate_unity_source("${_combinedFile}" ${_files} ${_dependsOption}) 3738 | endif() 3739 | 3740 | elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") 3741 | 3742 | cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") 3743 | 3744 | else() 3745 | message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".") 3746 | endif() 3747 | 3748 | else() 3749 | 3750 | # cotire is being run in include mode 3751 | # set up all variable and property definitions 3752 | 3753 | if (NOT DEFINED COTIRE_DEBUG_INIT) 3754 | if (DEFINED COTIRE_DEBUG) 3755 | set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) 3756 | else() 3757 | set (COTIRE_DEBUG_INIT FALSE) 3758 | endif() 3759 | endif() 3760 | option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) 3761 | 3762 | if (NOT DEFINED COTIRE_VERBOSE_INIT) 3763 | if (DEFINED COTIRE_VERBOSE) 3764 | set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) 3765 | else() 3766 | set (COTIRE_VERBOSE_INIT FALSE) 3767 | endif() 3768 | endif() 3769 | option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) 3770 | 3771 | set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING 3772 | "Ignore headers with the listed file extensions from the generated prefix header.") 3773 | 3774 | set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING 3775 | "Ignore headers from these directories when generating the prefix header.") 3776 | 3777 | set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING 3778 | "Ignore sources with the listed file extensions from the generated unity source.") 3779 | 3780 | set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "2" CACHE STRING 3781 | "Minimum number of sources in target required to enable use of precompiled header.") 3782 | 3783 | if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT) 3784 | if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) 3785 | set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}) 3786 | elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio") 3787 | # enable parallelization for generators that run multiple jobs by default 3788 | set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j") 3789 | else() 3790 | set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0") 3791 | endif() 3792 | endif() 3793 | set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING 3794 | "Maximum number of source files to include in a single unity source file.") 3795 | 3796 | if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) 3797 | set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") 3798 | endif() 3799 | if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) 3800 | set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") 3801 | endif() 3802 | if (NOT COTIRE_INTDIR) 3803 | set (COTIRE_INTDIR "cotire") 3804 | endif() 3805 | if (NOT COTIRE_PCH_ALL_TARGET_NAME) 3806 | set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") 3807 | endif() 3808 | if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) 3809 | set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") 3810 | endif() 3811 | if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) 3812 | set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") 3813 | endif() 3814 | if (NOT COTIRE_CLEAN_TARGET_SUFFIX) 3815 | set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") 3816 | endif() 3817 | if (NOT COTIRE_PCH_TARGET_SUFFIX) 3818 | set (COTIRE_PCH_TARGET_SUFFIX "_pch") 3819 | endif() 3820 | if (MSVC) 3821 | # MSVC default PCH memory scaling factor of 100 percent (75 MB) is too small for template heavy C++ code 3822 | # use a bigger default factor of 170 percent (128 MB) 3823 | if (NOT DEFINED COTIRE_PCH_MEMORY_SCALING_FACTOR) 3824 | set (COTIRE_PCH_MEMORY_SCALING_FACTOR "170") 3825 | endif() 3826 | endif() 3827 | if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) 3828 | set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") 3829 | endif() 3830 | if (NOT DEFINED COTIRE_TARGETS_FOLDER) 3831 | set (COTIRE_TARGETS_FOLDER "cotire") 3832 | endif() 3833 | if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) 3834 | if ("${CMAKE_GENERATOR}" MATCHES "Ninja") 3835 | # generated Ninja build files do not work if the unity target produces the same output file as the cotired target 3836 | set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") 3837 | else() 3838 | set (COTIRE_UNITY_OUTPUT_DIRECTORY "") 3839 | endif() 3840 | endif() 3841 | 3842 | # define cotire cache variables 3843 | 3844 | define_property( 3845 | CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" 3846 | BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." 3847 | FULL_DOCS 3848 | "The variable can be set to a semicolon separated list of include directories." 3849 | "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." 3850 | "If not defined, defaults to empty list." 3851 | ) 3852 | 3853 | define_property( 3854 | CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" 3855 | BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header." 3856 | FULL_DOCS 3857 | "The variable can be set to a semicolon separated list of file extensions." 3858 | "If a header file extension matches one in the list, it will be excluded from the generated prefix header." 3859 | "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." 3860 | "If not defined, defaults to inc;inl;ipp." 3861 | ) 3862 | 3863 | define_property( 3864 | CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS" 3865 | BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source." 3866 | FULL_DOCS 3867 | "The variable can be set to a semicolon separated list of file extensions." 3868 | "If a source file extension matches one in the list, it will be excluded from the generated unity source file." 3869 | "Source files with an extension in CMAKE__IGNORE_EXTENSIONS are always excluded." 3870 | "If not defined, defaults to m;mm." 3871 | ) 3872 | 3873 | define_property( 3874 | CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" 3875 | BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." 3876 | FULL_DOCS 3877 | "The variable can be set to an integer > 0." 3878 | "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." 3879 | "If not defined, defaults to 2." 3880 | ) 3881 | 3882 | define_property( 3883 | CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" 3884 | BRIEF_DOCS "Maximum number of source files to include in a single unity source file." 3885 | FULL_DOCS 3886 | "This may be set to an integer >= 0." 3887 | "If 0, cotire will only create a single unity source file." 3888 | "If a target contains more than that number of source files, cotire will create multiple unity source files for it." 3889 | "Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores." 3890 | "Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs." 3891 | "Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." 3892 | "Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise." 3893 | ) 3894 | 3895 | # define cotire directory properties 3896 | 3897 | define_property( 3898 | DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" 3899 | BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." 3900 | FULL_DOCS 3901 | "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." 3902 | ) 3903 | 3904 | define_property( 3905 | DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" 3906 | BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." 3907 | FULL_DOCS 3908 | "See target property COTIRE_ADD_UNITY_BUILD." 3909 | ) 3910 | 3911 | define_property( 3912 | DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" 3913 | BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." 3914 | FULL_DOCS 3915 | "See target property COTIRE_ADD_CLEAN." 3916 | ) 3917 | 3918 | define_property( 3919 | DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" 3920 | BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." 3921 | FULL_DOCS 3922 | "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." 3923 | ) 3924 | 3925 | define_property( 3926 | DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" 3927 | BRIEF_DOCS "Honor headers from these directories when generating the prefix header." 3928 | FULL_DOCS 3929 | "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." 3930 | ) 3931 | 3932 | define_property( 3933 | DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" 3934 | BRIEF_DOCS "Header paths matching one of these directories are put at the top of the prefix header." 3935 | FULL_DOCS 3936 | "See target property COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH." 3937 | ) 3938 | 3939 | define_property( 3940 | DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" 3941 | BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." 3942 | FULL_DOCS 3943 | "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." 3944 | ) 3945 | 3946 | define_property( 3947 | DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" 3948 | BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." 3949 | FULL_DOCS 3950 | "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." 3951 | ) 3952 | 3953 | define_property( 3954 | DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" 3955 | BRIEF_DOCS "Maximum number of source files to include in a single unity source file." 3956 | FULL_DOCS 3957 | "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." 3958 | ) 3959 | 3960 | define_property( 3961 | DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" 3962 | BRIEF_DOCS "Define strategy for setting up the unity target's link libraries." 3963 | FULL_DOCS 3964 | "See target property COTIRE_UNITY_LINK_LIBRARIES_INIT." 3965 | ) 3966 | 3967 | # define cotire target properties 3968 | 3969 | define_property( 3970 | TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED 3971 | BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." 3972 | FULL_DOCS 3973 | "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." 3974 | "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." 3975 | "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." 3976 | "The target name will be set to this target's name with the suffix _pch appended." 3977 | "Inherited from directory." 3978 | "Defaults to TRUE." 3979 | ) 3980 | 3981 | define_property( 3982 | TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED 3983 | BRIEF_DOCS "Add a new target that performs a unity build for this target." 3984 | FULL_DOCS 3985 | "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." 3986 | "Most of the relevant target properties will be copied from this target to the new unity build target." 3987 | "Target dependencies and linked libraries have to be manually set up for the new unity build target." 3988 | "The unity target name will be set to this target's name with the suffix _unity appended." 3989 | "Inherited from directory." 3990 | "Defaults to TRUE." 3991 | ) 3992 | 3993 | define_property( 3994 | TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED 3995 | BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." 3996 | FULL_DOCS 3997 | "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." 3998 | "The clean target name will be set to this target's name with the suffix _clean_cotire appended." 3999 | "Inherited from directory." 4000 | "Defaults to FALSE." 4001 | ) 4002 | 4003 | define_property( 4004 | TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED 4005 | BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." 4006 | FULL_DOCS 4007 | "The property can be set to a list of directories." 4008 | "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." 4009 | "Inherited from directory." 4010 | "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." 4011 | ) 4012 | 4013 | define_property( 4014 | TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED 4015 | BRIEF_DOCS "Honor headers from these directories when generating the prefix header." 4016 | FULL_DOCS 4017 | "The property can be set to a list of directories." 4018 | "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." 4019 | "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," 4020 | "the option which yields the closer relative path match wins." 4021 | "Inherited from directory." 4022 | "If not set, this property is initialized to the empty list." 4023 | ) 4024 | 4025 | define_property( 4026 | TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" INHERITED 4027 | BRIEF_DOCS "Header paths matching one of these directories are put at the top of prefix header." 4028 | FULL_DOCS 4029 | "The property can be set to a list of directories." 4030 | "Header file paths matching one of these directories will be inserted at the beginning of the generated prefix header." 4031 | "Header files are sorted according to the order of the directories in the property." 4032 | "If not set, this property is initialized to the empty list." 4033 | ) 4034 | 4035 | define_property( 4036 | TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED 4037 | BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." 4038 | FULL_DOCS 4039 | "This may be set to a semicolon-separated list of preprocessor symbols." 4040 | "cotire will add corresponding #undef directives to the generated unit source file before each target source file." 4041 | "Inherited from directory." 4042 | "Defaults to empty string." 4043 | ) 4044 | 4045 | define_property( 4046 | TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED 4047 | BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." 4048 | FULL_DOCS 4049 | "This may be set to a semicolon-separated list of preprocessor symbols." 4050 | "cotire will add corresponding #undef directives to the generated unit source file after each target source file." 4051 | "Inherited from directory." 4052 | "Defaults to empty string." 4053 | ) 4054 | 4055 | define_property( 4056 | TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED 4057 | BRIEF_DOCS "Maximum number of source files to include in a single unity source file." 4058 | FULL_DOCS 4059 | "This may be set to an integer > 0." 4060 | "If a target contains more than that number of source files, cotire will create multiple unity build files for it." 4061 | "If not set, cotire will only create a single unity source file." 4062 | "Inherited from directory." 4063 | "Defaults to empty." 4064 | ) 4065 | 4066 | define_property( 4067 | TARGET PROPERTY "COTIRE__UNITY_SOURCE_INIT" 4068 | BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one." 4069 | FULL_DOCS 4070 | "If set, cotire will only add the given file(s) to the generated unity source file." 4071 | "If not set, cotire will add all the target source files to the generated unity source file." 4072 | "The property can be set to a user provided unity source file." 4073 | "Defaults to empty." 4074 | ) 4075 | 4076 | define_property( 4077 | TARGET PROPERTY "COTIRE__PREFIX_HEADER_INIT" 4078 | BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one." 4079 | FULL_DOCS 4080 | "If set, cotire will add the given header file(s) to the generated prefix header file." 4081 | "If not set, cotire will generate a prefix header by tracking the header files included by the unity source file." 4082 | "The property can be set to a user provided prefix header file (e.g., stdafx.h)." 4083 | "Defaults to empty." 4084 | ) 4085 | 4086 | define_property( 4087 | TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED 4088 | BRIEF_DOCS "Define strategy for setting up unity target's link libraries." 4089 | FULL_DOCS 4090 | "If this property is empty or set to NONE, the generated unity target's link libraries have to be set up manually." 4091 | "If this property is set to COPY, the unity target's link libraries will be copied from this target." 4092 | "If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets." 4093 | "Inherited from directory." 4094 | "Defaults to empty." 4095 | ) 4096 | 4097 | define_property( 4098 | TARGET PROPERTY "COTIRE__UNITY_SOURCE" 4099 | BRIEF_DOCS "Read-only property. The generated unity source file(s)." 4100 | FULL_DOCS 4101 | "cotire sets this property to the path of the generated single computation unit source file for the target." 4102 | "Defaults to empty string." 4103 | ) 4104 | 4105 | define_property( 4106 | TARGET PROPERTY "COTIRE__PREFIX_HEADER" 4107 | BRIEF_DOCS "Read-only property. The generated prefix header file." 4108 | FULL_DOCS 4109 | "cotire sets this property to the full path of the generated language prefix header for the target." 4110 | "Defaults to empty string." 4111 | ) 4112 | 4113 | define_property( 4114 | TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" 4115 | BRIEF_DOCS "Read-only property. The generated precompiled header file." 4116 | FULL_DOCS 4117 | "cotire sets this property to the full path of the generated language precompiled header binary for the target." 4118 | "Defaults to empty string." 4119 | ) 4120 | 4121 | define_property( 4122 | TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" 4123 | BRIEF_DOCS "The name of the generated unity build target corresponding to this target." 4124 | FULL_DOCS 4125 | "This property can be set to the desired name of the unity target that will be created by cotire." 4126 | "If not set, the unity target name will be set to this target's name with the suffix _unity appended." 4127 | "After this target has been processed by cotire, the property is set to the actual name of the generated unity target." 4128 | "Defaults to empty string." 4129 | ) 4130 | 4131 | # define cotire source properties 4132 | 4133 | define_property( 4134 | SOURCE PROPERTY "COTIRE_EXCLUDED" 4135 | BRIEF_DOCS "Do not modify source file's build command." 4136 | FULL_DOCS 4137 | "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." 4138 | "The source file will also be excluded from the generated unity source file." 4139 | "Source files that have their COMPILE_FLAGS property set will be excluded by default." 4140 | "Defaults to FALSE." 4141 | ) 4142 | 4143 | define_property( 4144 | SOURCE PROPERTY "COTIRE_DEPENDENCY" 4145 | BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." 4146 | FULL_DOCS 4147 | "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." 4148 | "If the file is modified, cotire will re-generate the prefix header source upon build." 4149 | "Defaults to FALSE." 4150 | ) 4151 | 4152 | define_property( 4153 | SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" 4154 | BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." 4155 | FULL_DOCS 4156 | "This may be set to a semicolon-separated list of preprocessor symbols." 4157 | "cotire will add corresponding #undef directives to the generated unit source file before this file is included." 4158 | "Defaults to empty string." 4159 | ) 4160 | 4161 | define_property( 4162 | SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" 4163 | BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." 4164 | FULL_DOCS 4165 | "This may be set to a semicolon-separated list of preprocessor symbols." 4166 | "cotire will add corresponding #undef directives to the generated unit source file after this file is included." 4167 | "Defaults to empty string." 4168 | ) 4169 | 4170 | define_property( 4171 | SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" 4172 | BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." 4173 | FULL_DOCS 4174 | "If this property is set to TRUE, cotire will complete the current unity file and start a new one." 4175 | "The new unity source file will include this source file as the first one." 4176 | "This property essentially works as a separator for unity source files." 4177 | "Defaults to FALSE." 4178 | ) 4179 | 4180 | define_property( 4181 | SOURCE PROPERTY "COTIRE_TARGET" 4182 | BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." 4183 | FULL_DOCS 4184 | "cotire sets this property to the name of target, that the source file's build command has been altered for." 4185 | "Defaults to empty string." 4186 | ) 4187 | 4188 | message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.") 4189 | 4190 | endif() 4191 | -------------------------------------------------------------------------------- /cmake/x86-windows-static-custom.cmake: -------------------------------------------------------------------------------- 1 | set(VCPKG_TARGET_ARCHITECTURE x86) 2 | set(VCPKG_CRT_LINKAGE dynamic) 3 | set(VCPKG_LIBRARY_LINKAGE static) 4 | 5 | if (PORT MATCHES "^libiconv$") 6 | set(VCPKG_LIBRARY_LINKAGE dynamic) 7 | endif() 8 | -------------------------------------------------------------------------------- /scripts/build.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/build.ps1 -------------------------------------------------------------------------------- /scripts/clean.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/clean.ps1 -------------------------------------------------------------------------------- /scripts/generate.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/generate.ps1 -------------------------------------------------------------------------------- /scripts/helpers.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/helpers.ps1 -------------------------------------------------------------------------------- /scripts/post_build.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/post_build.ps1 -------------------------------------------------------------------------------- /scripts/prepare.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/prepare.ps1 -------------------------------------------------------------------------------- /scripts/prepare_prebuilt.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/prepare_prebuilt.ps1 -------------------------------------------------------------------------------- /scripts/vcpkg.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyubotics/coolq-cpp-sdk/6322e0c701e5c5f081128a6530ad4d814e614c02/scripts/vcpkg.ps1 -------------------------------------------------------------------------------- /src/demo.cpp: -------------------------------------------------------------------------------- 1 | #include "cqsdk/cqsdk.h" 2 | 3 | // namespace cq::app 包含插件本身的生命周期事件和管理 4 | // namespace cq::event 用于注册 QQ 相关的事件处理函数 5 | // namespace cq::api 用于调用酷 Q 提供的接口 6 | // namespace cq::logging 用于日志 7 | // namespace cq::message 提供封装了的 Message 等类 8 | 9 | // 插件入口,在静态成员初始化之后,app::on_initialize 事件发生之前被执行,用于配置 SDK 和注册事件回调 10 | CQ_MAIN { 11 | cq::app::on_enable = [] { 12 | // cq::logging、cq::api、cq::dir 等命名空间下的函数只能在事件回调函数内部调用,而不能直接在 CQ_MAIN 中调用 13 | cq::logging::debug(u8"启用", u8"插件已启动"); 14 | }; 15 | 16 | cq::event::on_private_msg = [](const cq::PrivateMessageEvent &e) { 17 | cq::logging::debug(u8"消息", u8"收到私聊消息:" + e.message + u8",发送者:" + std::to_string(e.user_id)); 18 | 19 | if (e.user_id != 1002647525) return; 20 | 21 | try { 22 | cq::api::send_private_msg(e.user_id, e.message); // echo 回去 23 | 24 | cq::api::send_msg(e.target, e.message); // 使用 e.target 指定发送目标 25 | 26 | // MessageSegment 类提供一些静态成员函数以快速构造消息段 27 | cq::Message msg = cq::MessageSegment::contact(cq::MessageSegment::ContactType::GROUP, 201865589); 28 | msg.send(e.target); // 使用 Message 类的 send 成员函数 29 | } catch (const cq::exception::ApiError &err) { 30 | // API 调用失败 31 | cq::logging::debug(u8"API", u8"调用失败,错误码:" + std::to_string(err.code)); 32 | } 33 | 34 | e.block(); // 阻止事件继续传递给其它插件 35 | }; 36 | 37 | cq::event::on_group_msg = [](const auto &e /* 使用 C++ 的 auto 关键字 */) { 38 | const auto memlist = cq::api::get_group_member_list(e.group_id); // 获取数据接口 39 | cq::Message msg = u8"本群一共有 "; // string 到 Message 自动转换 40 | msg += std::to_string(memlist.size()) + u8" 个成员"; // Message 类可以进行加法运算 41 | cq::message::send(e.target, msg); // 使用 message 命名空间的 send 函数 42 | }; 43 | } 44 | 45 | // 添加菜单项,需要同时在 .json 文件的 menu 字段添加相应的条目,function 字段为 menu_demo_1 46 | CQ_MENU(menu_demo_1) { 47 | cq::logging::info(u8"菜单", u8"点击了示例菜单1"); 48 | try { 49 | cq::api::send_private_msg(10000, "hello"); 50 | } catch (const cq::exception::ApiError &) { 51 | cq::logging::warning(u8"菜单", u8"发送失败"); 52 | } 53 | } 54 | 55 | #include 56 | 57 | // 不像 CQ_MAIN,CQ_MENU 可以多次调用来添加多个菜单 58 | CQ_MENU(menu_demo_2) { 59 | cq::logging::info(u8"菜单", u8"点击了示例菜单2"); 60 | MessageBoxW(nullptr, L"这是一个提示", L"提示", MB_OK | MB_SETFOREGROUND | MB_TASKMODAL | MB_TOPMOST); 61 | } 62 | -------------------------------------------------------------------------------- /vcpkg-requirements.txt: -------------------------------------------------------------------------------- 1 | boost-algorithm 2 | libiconv --------------------------------------------------------------------------------