Weeelll ... это возможно, но это не очень, и у него есть некоторые подводные камни. Это, как правило, лучше, чтобы добавить включать путь в системе сборки, такие как (предполагая, что простой make
):
# C PreProcessor flags. This variable is used by make's implicit rules for
# everything preprocessor-related.
CPPFLAGS += -I$(PROJECT_PATH)
и #include
заголовки без пути в исходном файле. Это сделает make
вызовом компилятора с -Iyour/project/path
, который заставит компилятор искать заголовки в your/project/path
. То есть, в Makefile вы можете иметь
PROJECT_PATH = foo/bar
CPPFLAGS = -I$(PROJECT_PATH)
и в источниках
#include "foobar.h"
иметь эффект #include "foo/bar/foobar.h"
.
... также, я видел, что вы пытаетесь использовать #include
исходные файлы вместо заголовков? Не спускайся по этой дороге; вниз, что безумие дороги лежит. Скомпилируйте исходные файлы отдельно и соедините их вместе обычным способом, если у вас нет действительно.
Итак, я не вижу причины, по которой вы хотели бы ссылаться на путь проекта непосредственно в директивах #include
в коде; единственное изменение на стороне сборки - это только то, что вы должны пройти -DPROJECT_PATH=foo/bar/
вместо -IPROJECT_PATH=foo/bar/
и что конструкция более хрупкая, чем механизмы, которые на самом деле предназначены для такого рода вещей. Но если вы действительно хотите сделать это, то вот как:
Первая проблема, вы столкнетесь в том, что
#include "foo/bar/" "baz.h" // no dice.
плохо сформирован, поэтому легкий путь выходит.Мы должны попытаться препроцессора магии, и он работает так:
#define HEADER_STRING(s) #s
#define HEADER_I(path, name) HEADER_STRING(path ## name)
#define HEADER(path, name) HEADER_I(path, name)
// v-- important: no spaces allowed here!
#include HEADER(PROJECT_PATH,foobar.h)
Возможно начинать снизу вверх:
#define HEADER_STRING(s) #s
делает строку из своего аргумента. То есть HEADER_STRING(foo/bar/baz.h)
расширяется до "foo/bar/baz.h"
. Примечательно, что макро-параметры не расширены, поэтому HEADER_STRING(PROJECT_PATH)
будет расширяться до "PROJECT_PATH"
, даже если задан макрос PROJECT_PATH
. Это одна из самых распространенных проблем, с которыми вы сталкиваетесь, когда вы пытаетесь сделать что-нибудь сложное с препроцессором, и решение добавить еще один слой, в котором параметры могут быть расширены:
#define HEADER_STRING_I(s) #s
#define HEADER_STRING(s) HEADER_STRING_I(s)
... мы делаем не нужно это для HEADER_STRING
, но он используется в HEADER
, поэтому держите трюк в уме. Боюсь, что точные правила подпроцессора для замещения несколько загадочны, и их подробное объяснение выходит за рамки ответа SO. В двух словах макросы расширяются в слоях, и когда макросы не расширяются, трюк обычно дает им место для расширения, то есть для добавления другого слоя.
HEADER_I
тогда
#define HEADER_I(path, name) HEADER_STRING(path ## name)
ленты его аргументы вместе и передает их HEADER_STRING
. HEADER_I(foo,bar)
- до HEADER_STRING(foobar)
. Из-за этой проблемы я уже упоминал выше, HEADER_I(PROJECT_PATH,foobar.h)
расширяется до HEADER_STRING(PROJECT_PATHfoobar.h)
, который, в свою очередь, расширяется до "PROJECT_PATHfoobar.h"
, поэтому нам нужен другой слой для расширения PROJECT_PATH
:
#define HEADER(path, name) HEADER_I(path, name)
Это только добавляет место для path
и name
параметров в быть расширена. Наконец, с PROJECT_PATH
#define
г в foo/bar/
, HEADER(PROJECT_PATH,foobar.h)
расширяется до "foo/bar/foobar.h"
, и тогда мы можем сказать
#include HEADER(PROJECT_PATH,foobar.h)
к #include "foo/bar/foobar.h"
. PROJECT_PATH
можно установить в файле makefile и передать с помощью -DPROJECT_PATH=$(some_make_variable)
.
Последняя ошибка заключается в том, что вы должны позаботиться о том, чтобы между токенами не было пробелов.
#include HEADER(PROJECT_PATH,foobar.h)
в конечном счете, расширяется до "foo/bar/ foobar.h"
(обратите внимание на пробел), который не работает.
Обычно вы обрабатываете такие файлы в своем make-файле и параметр -I, чтобы добавить исправления, рассмотренные для поиска включенных файлов. И да, используйте make (не CMake). –
Почему бы просто не использовать символическую ссылку? Отлично подходит для таких случаев. Отсутствие поддержки в Visual Studio (редактор не распознает, что два разных пути являются одним и тем же файлом) делает его менее практичным для файлов, которые редактируются в Windows, но (1) вы используете Linux, и (2) вы «Не будем редактировать файл по ссылке. –
@ Cheersandhth.-Alf Aaahrg! Мой коллега раздражает всех остальных своей символической системой построения дерева ссылок. Есть намного лучшие способы сделать это с make (например, 'vpath' является одним). –