Поэтому я думаю, что то, что я пытаюсь сделать, просто невозможно в GCC из-за расширения макросов, которое должно привести к токену препроцессора. Это отлично работает в MSVC++, чего бы это ни стоило, но я не могу найти сопоставимого
Поэтому я думаю, что это невозможно в GCC (отлично работает в VC++) из-за расширения макросов, которые должны быть токенами препроцессора и тем, что считается разделителем между токенами.
Я пытаюсь связать определенную версию библиотеки, в этом примере это Lua 5.3.1. У меня есть файлы, извлеченные в мою исходную папку, чтобы их можно было найти в подпапке «lua-5.3.1\src», и я хотел бы написать макрос, который я могу использовать для префикса файлов заголовков с этим путем. Что-то простое, например LUA_PATH(_file)
, которое расширится до "lua-5.3.1/src/_file"
. Обычно я бы просто использовал флаги компилятора, чтобы указать другую подпапку для поиска, но из-за того, как настроены проекты, над которыми я работаю, это именно то, что я не могу сделать и что я пытаюсь найти другой путь необходимость поддерживать включаемые пути повсюду.
Вот небольшой файл, который я написал (он не компилируется, но я могу запустить его через cpp, чтобы посмотреть, что он мне даст)
#define LUASRC lua-5.3.1/src/
#define STRINGIFY(_s) #_s
#define ADDLUAPATH(_path, _file) STRINGIFY(_path ## _file)
#define EVALUATOR(_path, _file) ADDLUAPATH(_path,_file)
#define LUA_PATH(_file) EVALUATOR(LUASRC,_file)
void main (void)
{
OUTPUTOFMACROHERE => LUA_PATH(lua.h)
}
Это дает мне следующий результат запуска cpp в файле
$ cpp temp.c
# 1 "temp.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "temp.c"
void main (void)
{
temp.c:1:29: error: pasting "/" and "lua" does not give a valid preprocessing token
#define LUASRC lua-5.3.1/src/
^
temp.c:3:44: note: in definition of macro 'ADDLUAPATH'
#define ADDLUAPATH(_path, _file) STRINGIFY(_path ## _file)
^
temp.c:5:25: note: in expansion of macro 'EVALUATOR'
#define LUA_PATH(_file) EVALUATOR(LUASRC,_file)
^
temp.c:5:35: note: in expansion of macro 'LUASRC'
#define LUA_PATH(_file) EVALUATOR(LUASRC,_file)
^
temp.c:9:23: note: in expansion of macro 'LUA_PATH'
OUTPUTOFMACROHERE => LUA_PATH(lua.h)
^
OUTPUTOFMACROHERE => "lua-5.3.1/src/lua.h"
}
По-настоящему разочаровывающая часть этого заключается в том, что вторая с последней строки - это именно тот результат, который я пытаюсь получить. Просто GCC считает попадание туда ошибкой.
Проблема в символе / в конце пути. Если вы возьмете / out в конце определения LUASRC и запустите его, вы получите OUTPUTOFMACROHERE => "lua-5.3.1/srclua.h"
без каких-либо ошибок ... за исключением того, что путь недействителен. Я не могу найти место, куда можно поместить символ, чтобы он попал в выходную строку в кавычках. Я пытался добавить его отдельно, например, _path ## / ## _file
, или переместить его в значение, переданное, например, LUA_PATH(/lua.h)
. Это просто жалуется на то, что с ним сочетается (src или lua) как с недопустимым токеном препроцессора.
Я пытался просто использовать строки для конкатенации препроцессора, но #include "string" "string"
, кажется, просто пытается включить обе эти строки как отдельные пути. Ясно, что папка не может быть открыта, и точный файл не может быть найден без поиска подпапок. Это также было результатом того, что половина переменных (путь или файл) была строкой, которую нужно добавить к другому расширенному и строковому значению. Это также является результатом простой попытки префикса моих файлов с путем, который должен быть расширен, #include LUASRC"lua.h"
(в документации GCC сказано, что если он не находит ‹ или ", он рассматривает значение для расширения макроса)
Есть ли другая стратегия, чтобы заставить его любить / в определении макроса, которого мне не хватает? Хотелось бы знать.
Я использую gcc версии 4.8.2 (Ubuntu 4.8.2-19ubuntu1).
РЕДАКТИРОВАТЬ: Логика, чтобы на самом деле сделать это, но более важные причины, по которым этого не делать, приведены в ссылке на ответ, отмеченный ниже. Однако для быстрой справки обо всем, вот как в итоге выглядел мой маленький файл temp.c
#define LUASRC lua-5.3.1/src/
#define EXPAND(_a) _a
#define STRINGIFY(_s) #_s
#define EVALUATOR(_args) STRINGIFY(_args)
#define LUA_PATH(_file) EVALUATOR(EXPAND(LUASRC)EXPAND(_file))
void main (void)
{
OUTPUTOFMACROHERE => LUA_PATH(lua.h)
}