Получить выходное имя цели в виде строки во время компиляции в C ++ - PullRequest
6 голосов
/ 04 марта 2011

У меня есть проект, который компилируется на нескольких платформах ... Windows, Unix, Linux, SCO, назовите ваш вкус.

Я бы хотел вставить имя выходной цели в переменную в исходном коде проекта(имя выходной программы, DLL, SO-библиотеки или чего-либо еще), чтобы я мог использовать его в сообщениях как общий способ ссылки на имя компонента, будь то EXE-файл в Windows, DLL-библиотека, SO-библиотека в Unix и т. д.

Я имею в виду ключ препроцессора, такой как FUNCTION _, но для чего-то, чтобы извлечь имя EXE / DLL в Windows в Visual C ++, а затем во вторую библиотеку вывода SO в GCC,Конечно, это, вероятно, два разных механизма, но я рассчитываю объединить эти два в один вариант, который я могу использовать в моем многоплатформенном коде в общем.

Итак, макрос или что-то, что я могу назвать, которыйпо крайней мере, выбирает имя выходного файла Windows во время компиляции (Visual C ++), чтобы я мог вставить его в константную строку в коде, и, возможно, способ сделать то же самое в GCC, чтобы две платформы могли быть объединены в одну абстракцию,Желательно не собирать во время выполнения, но перехватывать и сохранять во время компиляции.

Если вывод представляет собой библиотеку, то это имя файла lib.Если это компонент, то имя файла выходного компонента.

Я предполагаю, что Boost или Poco должны иметь что-то подобное, возможно, с некоторыми неподдерживаемыми конечными точками, что нормально.

Ответы [ 3 ]

9 голосов
/ 04 марта 2011

Если все вместе в одном проекте, вы можете использовать макрос препроцессора. Чтобы сделать это в Visual Studio, откройте свойства вашего проекта и перейдите в Свойства конфигурации> C / C ++> Препроцессор и добавьте что-то вроде PROGRAM_NAME="\"$(ProjectName)\"" в поле «Определения препроцессора» (что соответствует опции компилятора /Dfoo=bar).

Для GCC используйте аналогичный параметр командной строки -Dfoo=bar. Например, ваш Makefile может выглядеть примерно так:

PROGRAM_NAME = myapplication
CFLAGS += '-DEXECUTABLE_NAME="$(PROGRAM_NAME)"'

# Rule to make the executable from the object files
$(PROGRAM_NAME): $(OBJS)
    $(LD) $(OBJS) -o $@ $(LDFLAGS)

# Rule to make object files from C source files
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

Это позволяет вашим исходным файлам использовать макрос PROGRAM_NAME, который в этом случае расширится до постоянной строки "myapplication".

Однако, если у вас есть объектные файлы, которые связаны с несколькими программами (например, у вас много общего кода библиотеки, который может быть запущен либо драйвером основной программы, либо различными тестовыми наборами), то объектные файлы не могут заранее знать, к какому исполняемому файлу они подключены, поэтому они должны определить это во время выполнения.

В этом случае используйте постоянную глобальную переменную для хранения имени программы, а также определите и инициализируйте его в основном исходном файле каждого исполняемого файла, используя описанную выше технику.

1 голос
/ 04 марта 2011

Другое решение, немного хакерское, состояло бы в том, чтобы установить вашу константную строку в коде на уникальное, легко обнаруживаемое и достаточно большое значение, и после того, как соединение выполнено, найдите и перезапишите уникальное значение с фактическим именем файла, который выработаете на ...

1 голос
/ 04 марта 2011

Компилятор не может этого знать.Это компоновщик, который назначает имя.Я бы сказал, что ваша лучшая ставка - это определение или время исполнения, определяющее имя модуля (которое не будет работать для статических библиотек)

...