问题标签 [precompiler]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
532 浏览

c - 包含的头文件是否在C文件中展开

以下面这个非常简单的 C 程序为例。我的理解是首先调用预编译器来扩展宏和头文件等。

我的理解是,预编译器会在编译之前首先将头文件stdio.h中的所有代码(声明)包含在 C 文件中,因此使 C 文件更大并且行号不同,因此printf()调用将进一步下降文件。

如果是这样,为什么在调试期间行号仍然正确?

0 投票
1 回答
99 浏览

c - 修改 gcc 编译以提高嵌入式 Flash 大小

介绍

我的 Cortex-M4 设备上的 Flash 快用完了。我分析了代码,减少代码大小的最大机会就是在预定义的常量中。

- 例子

问题

问题是我有(大量)(短)字符串要存储,但它们中的大多数用于表中 - const structs 数组具有指向const与数字数据混合的字符串的指针。每个字符串的大小都是可变的,但是我仍然考虑更改struct指针以保存一个简单的(最大)char数组而不是指针 - 并没有太大区别。编译器希望在 4 字节边界上开始每个新字符串并没有帮助。这让我想到...

主意

如果我可以将 4 字节char指针替换index为字符串表中的 2 字节 - 一个预定义的链接器部分,它index是一个偏移量 - 我会在那里为每条记录节省 2 个字节,但会以轻微的代码碰撞为代价。我也会避免内部填充,因为每个字符串都可以在前一个字符串的NUL字节之后立即开始。如果我能聪明点,我可以为索引重用字符串——甚至是部分字符串。

但此外,我会将4 + 2 + 4 (+ 2)对齐方式更改为2 + 2 + 2- 节省更多空间!

- 考虑

当然,在源代码中,所有这些字符串以及字符串表本身的内务管理将是一场噩梦……除非我能让编译器帮忙?我想改变实际源代码的语法:如果我希望字符串出现在字符串表中,我会将其写为#"String",其中#前缀会将其标记为字符串表候选者。一个普通的字符串不会有那个前缀,编译器会把它当作普通的。

执行

因此,要实现这一点,我必须编写一个预编译器。只处理#""字符串,用“神奇”的 16 位偏移量替换它们,然后将其他所有内容输出到真正的(预)编译器以进行实际编译。预编译器还必须编写一个C包含完整字符串表的新文件(尽管有一个技巧 - 见下文),以便编译器解析并提供给链接器的专用部分。使用开关调用它会很容易-no-integrated-cpp,调用我自己的预处理器,然后调用真正的预处理器。

- 问题

不要误会我的意思;我知道有问题。例如,它必须能够处理部分构建。我的解决方案是,对于每个修改过的C文件,它会(如有必要)编写一个并行字符串表文件。“主”C字符串表文件只不过是一系列s,如果其中一个s 已更改,或者实际上,如果添加了新#include的,则构建将意识到需要重新编译。#include#include

结果

结果将是一个可执行文件,它将所有(常量)字符串打包到一个不大于 64K 的内存块中(这不是问题!)。代码会知道这index将是该 blob 的偏移量,因此会在正常使用它之前将索引添加到字符串表指针的开头。

问题

我的问题是:值得吗?

- 优点:

  • 它将节省一空间。我没有在上面量化它,但假设节省了总 Flash 的 5%(!)。

- 缺点:

  • 这将需要修改构建过程以包含定制的预处理器;
  • 该预处理器必须作为工具链而不是项目的一部分来构建;
  • 预处理器可能有错误或限制;
  • 真正的源代码不会“开箱即用”编译。

现在...

我已经穿上了我的石棉套装,所以... GO!

0 投票
0 回答
63 浏览

c - 如何使用预编译器开关为 C 项目启用迭代构建?

我正在为五个不同的嵌入式控制器开发 C 代码。过去,我曾经为每个控制器创建一个单独的项目,但共享代码量约为 98%。因此,我合并了所有项目,并通过预处理器宏抽象了硬件访问。例子:

编译器:

代码:

这种解决方案节省了大量时间,而且效果很好。不幸的是,迭代构建不起作用。如果我构建控制器 A,我的构建环境 'sCons' 的决策者会为其构建的每个文件创建一个 MD5 校验和。当我切换到控制器 B 时,只更改了预处理器宏。因此,MD5 校验和保持不变,并且决定程序没有检测到任何更改并拒绝重建文件。

我可以在 sCons 中实现并注册一个自定义决策器,但这听起来很麻烦。这个问题已经有解决方案了吗?如果他们提供原生解决方案,我会毫不犹豫地切换到 cMake 或 Gradle。从我的角度来看,任何解决方案都需要在调用决策者之前运行预处理器。

PS:我知道 Keil Arm IDE 自带这个功能,但是我想要并且需要使用我自己的构建环境。

0 投票
1 回答
41 浏览

objective-c - 如何将 Objective-C 中的模块导入调整为一些最小的操作系统版本?

我正在开发一个针对所有 Apple 操作系统(macos、ios、watchos、tvos)的 Objective-C 库。我使用的一些 Apple API 只能从特定版本的操作系统开始使用。我确实使用以下方法保护我的接口定义和操作系统版本相关代码:

但是,我的模块导入似乎也导致我的库的基于 Cocoapods 的构建失败。例如,如果 OSLog 模块仅在根据上述 API_AVAILABLE(...) 规范开始的操作系统中可用,我确实需要@import OSLog;使用类似于上述 API_AVAILABLE(...) 的 #if 预编译器条件来保护它。

假设我的假设是正确的,我应该怎么做呢?

0 投票
1 回答
292 浏览

c++11 - static_assert 抛出错误“静态断言的非常量条件”

为什么此代码是非常量条件?

但这不是:

请参阅Godbolt上的代码。注意:使用 gcc <9 秒的代码也有错误。

0 投票
1 回答
48 浏览

c# - 如何用 C# 代码替换预处理器指令,预处理器指令的替代方法

我们使用的是前处理器指令,如 trail 和 license,所以我们有两个安装程序用于 trail 和 license。当用户想要从试用升级到许可时,他们必须卸载试用并安装许可,反之亦然。现在我们只想拥有一个安装程序,这意味着我们希望摆脱重新安装应用程序以获取许可的过程,并且只有一个为 Trail 和许可用户提供服务的安装程序。所以我的问题是基于一些许可文件,即 DAT文件,我们应该如何使用 C# 代码更改预处理代码 在用户升级或降级许可证后更改代码的替代方法是什么。如果许可证有任何变化,那么我们需要使用 Main 方法并重新加载会话和所有异常处理程序,引擎再次打开相应的模式。请建议如何为这种挑战编码。

0 投票
1 回答
46 浏览

openssl - 有什么办法可以避免 pro*c 预编译器?

我一直在尝试在 Oracle tuxedo 上使用 openSSL,但它的 pro-c 编译器不断出错。人们说 pro*c 预编译器无法处理 c99 语法中的代码。

我想知道我的代码如何避免预编译器。

根据openssl github问题(https://github.com/openssl/openssl/issues/9778

“ 用定义包装你的代码并将其添加到 proc 调用中。Oracle 预处理器将禁用该代码路径”</p>

我不知道该怎么做。我试过这样,但它不起作用。#ifndef precomp_test #define precomp_test #include <openssl/ssl.h> #endif

到目前为止,我所做的只是包括 ssl.h。谁能告诉我如何避免预编译器?

0 投票
2 回答
68 浏览

c++ - 有没有办法将预编译器列表与 C++ 宏合并/连接?

我有两个清单:

并使用 C++ 宏我想写这样的东西:

产生:

在编译期间。

这样的事情可能吗?还有其他关于字符串的问题,但是我一生都无法弄清楚如何使用非字符串数组声明来做到这一点。

编辑:我当然宁愿不使用宏,并且希望列表格式也不同。不幸的是,包含这些列表定义的头文件不是我可以编辑的文件。