简体   繁体   English

条件编译的混乱和失败

[英]Conditional compilation confusion and failure

I want to compile different files with a common *.c file. 我想用一个通用的* .c文件来编译不同的文件。 Like I want to compile Ac common.c xor Bc common.c but I can't figure out how to achieve that. 就像我要编译Ac common.c Bc common.c但我不知道如何实现。

Can you please tell me how do I make common.c use different headers without using my text editor to change the headers list every time I want to compile 能否请您告诉我如何使common.c使用不同的头文件,而不必在每次编译时都使用文本编辑器来更改头文件列表

So let's say I have 3 files: Ac, Bc and common.c. 假设我有3个文件:Ac,Bc和common.c。

Ah and Bh define an enum enum {Mon, Tues, Wed...} in different ways. Ah和Bh以不同的方式定义枚举enum {Mon, Tues, Wed...} And that enum is used in common.c. 该枚举用于common.c。 So I can't just do in common.c: 所以我不能只做common.c:

#include "A.h"
#include "B.h"

What I thought of doing is to use preprocessor directives: 我想做的是使用预处理器指令:

In common.h 共同点

#define A 1
#define B 2

In Ac 在交流中

#define COMPILE_HEADER A

And in common.c 和共同点

#if COMPILE_HEADER == A 
#include A.h 
#end

This doesn't work, of course, because the compiler didn't visit the Ac file to find #define COMPILE_HEADER A 当然,这不起作用,因为编译器没有访问Ac文件来查找#define COMPILE_HEADER A

So can you please tell me how do I make common.c use different headers without using my text editor to change the headers list every time I want to compile? 因此,能否请您告诉我如何使common.c使用不同的头文件,而不必每次使用编译器时都使用文本编辑器来更改头文件列表?

It's pretty complicated to explain, but I'll give it a try. 解释起来相当复杂,但我会尝试一下。

Explaination 讲解

The compiler, for example gcc, gets the input files provided, includes (literally just copy-pastes) the header files into their respective places (where the #include directive is located) in the *.c file, then compiles the file to the object ( *.o ) file. 编译器(例如gcc)获取提供的输入文件,将头文件包括(实际上只是复制粘贴)到*.c文件中的相应位置( #include指令所在的位置)中,然后将文件编译为对象( *.o )文件。 No executable is created. 没有创建可执行文件。 Here comes the linker, which is included in gcc. 这是链接器,它包含在gcc中。 It takes the *.o files and links them into one executable. 它使用*.o文件并将它们链接到一个可执行文件中。

The problem is, that the files are compiled independently, and then linked together. 问题在于,文件是独立编译的,然后链接在一起。 I mean, that predefinition like int func(int param); 我的意思是,像int func(int param);这样的预定义int func(int param); is like saying to compiler "Hey man, don't worry about any usage of func in the code, the linker will care". 就像对编译器说的“嘿,伙计,不用担心在代码中使用func ,链接器会在意的”。 Compiler then just saves this usage as external symbol in the corresponding *.o file, and when linker is doing his job, he firstly finds the location of the symbol definition (the function implementation) and then just points to it whenever the func is called. 然后,编译器仅将此用法另存为外部符号在相应的*.o文件中,并且在链接程序执行其工作时,他首先查找符号定义(函数实现)的位置,然后在调用func时仅指向它。

Try to include function definition in header file, then include it in 2 or more files from same project (compiled/linked together). 尝试将函数定义包含在头文件中,然后将其包含在同一项目的2个或多个文件中(编译/链接在一起)。 Compiler will say it's ok, since the code is correct and the generated code is valid. 编译器会说没问题,因为代码正确且生成的代码有效。 Then, the linker will try to link it into one executable and he would have to decide which version of the same name-param function should it link to. 然后,链接器将尝试将其链接到一个可执行文件中,并且他将不得不决定链接到同一名称-参数函数的哪个版本。 Since most developer tools are not really good at making the right choices, he will just yell at you saying "hey man, you gave me two definitions of same function, what to do now?". 由于大多数开发人员工具并不真正擅长做出正确的选择,因此他只会对您大喊:“嘿,您给了我两个相同功能的定义,现在该怎么办?”。 This results with an error like this: 结果是这样的错误:

obj\Release\b.o:b.cpp:(.text+0x0): multiple definition of 'func(int)'
obj\Release\a.o:a.cpp:(.text+0xc): first defined here

What about having two main in one project? 一个项目中有两个main项目又如何呢?

obj\Release\b.o:b.cpp:(.text.startup+0x0): multiple definition of 'main'
obj\Release\a.o:a.cpp:(.text.startup+0x0): first defined here

Both files compile, but they cannot be linked together. 这两个文件都可以编译,但是不能链接在一起。

The header files are meant to contain class definitions and function predefinitions to allow you to write them only once, and then share between all files that want to use them. 头文件旨在包含类定义和函数预定义,以使您仅可以编写一次,然后在要使用它们的所有文件之间共享。 You can always just type class definitions for each file separately (as long as they stay same) and use them just like you would use them in .h file, same applies for function predefinitions. 您始终可以只为每个文件分别键入类定义(只要它们保持相同),就可以像在.h文件中使用它们一样使用它们,同样适用于函数预定义。

There comes your problem. 你的问题来了。 You have to compile only one file, not include only one. 您只需要编译一个文件,而不必仅编译一个文件。 You can do this by using the preprocessor trick, but I wouldn't reccomend as solution, since it can be solved much easier (I'll tell you how in a moment). 您可以使用预处理器技巧来做到这一点,但是我不建议您将其作为解决方案,因为它可以更轻松地解决(我将在稍后告诉您)。

TL;DR; TL; DR; (The actual answer without explaination) (实际答案无解释)

You can #ifdef / #ifndef both files, then in another *.c define (or not define) some value. 您可以#ifdef / #ifndef这两个文件,然后在另一个*.c定义(或不​​定义)某些值。 For example: 例如:

A.cpp 丙型肝炎

#include "t.h"

#ifdef USE_A
int func(int a)
{
    return a + 5;
}
#endif

B.cpp 丙型肝炎

#include "t.h"

#ifndef USE_A
int func(int a)
{
    return a * 10;
}
#endif

Th

#ifndef T_H
#define T_H

//Or comment to use B
#define USE_A

int func(int a);

#endif // T_H

main.cpp main.cpp

#include <iostream>
#include "t.h"

using namespace std;

int main()
{
    cout << func(3);
}

Notice that the #ifdef / #ifndef are after the #include , so the preprocessor knows which one to compile. 注意, #ifdef / #ifndef #include ,因此预处理程序知道要编译哪个。 Also, it's not possible (at least I can't think of any way) to make the definition in any .c file, because they are compiled separately (as described above). 另外,不可能(至少我想不出任何办法)在任何.c文件中进行定义,因为它们是分别编译的(如上所述)。 You could use the -D switch, but that involves messing with build configurations in environments and if you want to do that it's better to try the second solution presented bellow. 您可以使用-D开关,但这涉及到环境中的构建配置的混乱,如果要这样做,最好尝试下面介绍的第二个解决方案。

Better answer 更好的答案

You should choose one file to compile with each version. 您应该选择一个文件以与每个版本一起编译。 It hardly depends on your needs, but basically instead of using g++ main.cpp a.cpp b.cpp you should compile either a.cpp or b.cpp. 它几乎不取决于您的需求,但是基本上应该使用a.cpp或b.cpp来代替使用g++ main.cpp a.cpp b.cpp b.cpp。 If you are using integrated environment like Visual Studio or Code Blocks, the configuration managers allow you to decide which file to include. 如果您使用的是Visual Studio或代码块之类的集成环境,则配置管理器允许您决定要包含的文件。 I mean, those Debug/Release dropdowns can contain your own entries, which will customize your project. 我的意思是,这些“调试/发布”下拉列表可以包含您自己的条目,这些条目将自定义您的项目。 Then, switching between the A.cpp and B.cpp is just a question of choosing appropiate option in the always-visible bar in your environment. 然后,在A.cpp和B.cpp之间切换只是在环境中始终可见的栏中选择适当选项的问题。

If you want a more detailed tutorial on how to manage configurations on Code::Blocks or Visual Studio create appropiate question on stackoverflow and it will be answered in no time :) 如果您想获得有关如何在Code :: Blocks或Visual Studio上管理配置的更详细的教程,请在stackoverflow上创建适当的问题,它将很快得到答复:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM