Is there a way to detect a C file compiled directly into an executable?

I would like to include testing main-functions in some C files so that they can be compiled into separate small programs for independent testing of various functions.

But I do not need these multiple main-functions included in the real (large) executable / library.

Obviously, I can use my own define, such as -DINCLUDE_TEST_MAIN, but it occurred to me that clang may already be telling me itself. Somehow ...

So, is there any way for compiled code to detect when it compiles directly to an executable file, and when a file object (with a flag -c) is created?

The solution does not have to be universal - I'm pretty sure universal does not exist - my main compiler is clang ...

+4
source share
3 answers

I do not see a better solution than -DINCLUDE_TEST_MAIN. You could probably create some fancy command line that would strip the bulk of the object file if you don't need it, but I think that -Dis the best way to go.

, ", , . -..." , , clang , -DMIKHAIL_T_INCLUDE_TEST_MAIN; , , .

, stuff.c, stuff.main.c :

gcc stuff.c stuff.main.c -o stuff.test

( .)

+4

( ) -Xlinker -zmuldefs.

, , , , , , .

, , , .c.

, , -zmuldefs , , , , .

-Dxxx , , ( , -zmuldefs , , , - , ).

, , . main() , , , , .

, -zmuldefs, , , .

, 2 , x1.c x2.c,

x1.c:

#include <stdio.h>

#include "x2.h"

int x();

int main() {
    x();
}

int x() {
    static int isRecursiveCall_ = 0;

    printf("Hello, World 1!\r\n");

    if (!isRecursiveCall_) {
        isRecursiveCall_ = 1;
        main();
        x3();
        isRecursiveCall_ = 0;
    }
    return 0;
}

x2.c:

#include <stdio.h>

#include "x2.h"

int main() {
    printf("Hello, World 2!\r\n");
    x3();
    return 0;
}

int x3() {
    printf("Hello, World 3!\r\n");
    return 0;
}

x2.h

#ifndef LINKTEST_X_H
#define LINKTEST_X_H

int main2();
int x2();
int x3();

#endif //LINKTEST_X_H

clang x2.c -Xlinker -zmuldefs -o test.o ./test.o :

Hello, World 2!
Hello, Wolrd 3!

clang x1.c x2.c -Xlinker -zmuldefs -o prog.o ./prog.o, :

Hello, World 1!
Hello, World 1!
Hello, World 3!

.

, - , -Dxxx, .

-Dxxx . , x2.c :

#include <stdio.h>

#include "x2.h"

#ifdef _UNIT_TEST_ENABLED
int main() {
    printf("Hello, World 2!\r\n");
    x3();
    return 0;
}
#endif

int x3() {
    printf("Hello, World 3!\r\n");
    return 0;
}

, x2.c, clang x2.c -DUNIT_TEST_ENABLED -o test.o, clang x1.c x2.c -o prog.o.

, script, . . , , .

, #define , , . , , , .

+2

.o- . .

, . Makefile:

OBJS = some_file.o other_file.o

test_prog: $(OBJS) test_main.o

real_prog: $(OBJS) real_main.o

all: test_prog real_prog

, - , make.

. .

, . , .

If disk space is a problem, you can use the centuries-old trick of creating a symbolic link to the main executable file with a different name, and then look at argv [0] and change the behavior of the program depending on the name called with.

+1
source

Source: https://habr.com/ru/post/1657891/


All Articles