Подготовка кода
Программы C не могут просто использовать символы C ++.Если только авторы кода C ++ не устроили это.Это связано с тем, что некоторые функции, которые предлагает C ++, такие как перегрузка функций (наличие нескольких функций с одинаковым именем, но с разными формальными аргументами), требуют, чтобы имя функции было искажено каким-либо образом.В противном случае компоновщик будет видеть один и тот же символ, определенный несколько раз.Компиляторы C не понимают искажение имени и поэтому не могут использовать символы C ++.Как правило, существует два возможных решения.
- Объявите и определите все символы C ++, которые код C хочет использовать в блоках
extern "C" { ... }
, и пусть ваши инструменты C ++ обрабатывают связывание.Код C в этом случае изменять не нужно. - Скомпилируйте код C с помощью (точно такого же) компилятора C ++, что и код C ++.Исправьте жалобы компилятора C ++ на код C по мере их возникновения.В зависимости от размера проекта и стиля кодирования, это может быть или не быть большой работой.
Подготовка мастер-файла Makefile
Лично я стараюсь не связываться с Makefileами других людей,особенно если они могут быть изменены или сложны.Итак, предполагая, что создание Make-файла, который управляет уже имеющимися у вас битами (в отличие от написания одного Make-файла, включающего все), в порядке, я бы начал с чего-то похожего на это:
Я предполагаю, что
- Один из вышеупомянутых вариантов был реализован
- Код для
mcce.a
находится в подкаталоге mcce/lib/
other_labs_code.cpp
лежит в other_labs_code/
- Функция
main
, которую вы хотите использовать, находится в ./mystuff.c
следующий Makefile верхнего уровня может помочь вам начать
CXX = c++
CXXFLAGS = -m64 # From other_labs_code/Makefile
LDFLAGS = -m64 -L<path to OEDIR> # From other_labs_code/Makefile
LIBS = -lgdbm -lm -lz # From mcce/lib/Makefile
LIBS += -loezap \ # From other_labs_code/Makefile
-loegrid \
-loefizzchem \
-loechem \
-loesystem \
-loeplatform \
-lpthread
mystuff: mystuff.c mcce/lib/mcce.a other_labs_code/other_labs_code.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
mcce/lib/mcce.a:
cd mcce/lib/ && $(MAKE) CC="$(CXX) -m64" mcce.a
other_labs_code/other_labs_code.o:
cd other_labs_code/ && $(MAKE) other_labs_code.o
Makefile: mcce/lib/Makefile other_labs_code/Makefile
echo "Warning: `pwd`/$@ is out of date" >&2
Этот Makefile будетиспользовать существующие Make-файлы подпроекта для выполнения компиляции.Если Make-файлы подпроекта имеют более новую временную метку, чем этот Makefile, что потенциально делает их устаревшими, об этом будет предупреждено.Связывание в основном работает путем объединения необходимых библиотек обоих подпроектов.Я удалил дубликаты.Переключатели компилятора в основном соответствуют исходным авторам, поскольку компиляция делегирована подпроектам.Код, который генерируют оба подпроекта, должен быть для одной и той же платформы.Если ваш компилятор gcc / g ++, то либо -m64
является значением по умолчанию и, следовательно, является избыточным во втором проекте, или его следует добавить в первый проект.Я проиллюстрировал внедрение этого кода в первый проект без изменения их Makefile (используя GNU make).Примечание: этот пример также вызывает компиляцию первого проекта с помощью компилятора C ++.
Блок extern "C" {...}
, расположенный в заголовочном файле C или C ++, который код C хочет включить, должен выглядеть следующим образом
/* inclusion guard etc */
#if defined(__cplusplus)
extern "C" {
#endif
/* C declarations */
#if defined(__cplusplus)
}
#endif
/* inclusion guard etc */
Незначительные точки
В первом опубликованном Makefile я предлагаю изменить нижнюю часть на
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(OBJ) mcce.a
.PHONY: clean
, что немного чище.
ВторойMakefile сломан сломан .Нижнее правило связывает двоичный файл и затем копирует его в каталог с именем bin, если он существует, в противном случае создается копия файла с именем `bin '.Если связывание не удается, этот факт не передается вызывающей стороне, то есть ошибка игнорируется.Нижнее правило должно иметь вид
mcce: mcce.c lib/mcce.h lib/mcce.a
$(CC) -o $@ mcce.c lib/mcce.a -lgdbm -lm -lz -fopenmp
cp mcce bin/
, т. Е. Команда link должна находиться в отдельной строке, а то, что bin должен быть каталогом, должно быть явным.