У меня есть каталог, содержащий заголовки и исходный код небольшой коллекции любительских программ OpenGL. Моя цель — создать два основных заголовочных файла: «toolbox.h» и «geometry.h». Второе #include это первое. Я также хотел бы, чтобы для удобства источники, связанные с этими двумя заголовками, были объединены в два архива. Когда я make 01_Planet-Geom, ни один из символов из «toolbox.h» не найден, несмотря на то, что я включил его архив в правило make. make 00_Dyn-6D работает отлично.
Что мне нужно изменить, чтобы make 01_Planet-Geom?
01_Planet-Geom: 01_Planet-Geom.o toolbox.a geometry.agcc $(CFLG) -o [email protected] $^ $(LIBS)make 01_Planet-Geom из каталога проекта.Я получаю следующий результат:
gcc -c -O3 -Wall -std=gnu17 01_Planet-Geom.c
gcc -c -O3 -Wall -std=gnu17 TriNet.c
ar -rcs geometry.a toolbox.a TriNet.o
gcc -O3 -Wall -std=gnu17 -o 01_Planet-Geom.out 01_Planet-Geom.o toolbox.a geometry.a -lglut -lGLU -lGL -lm
/usr/bin/ld: geometry.a(TriNet.o): in function `N_from_VF':
TriNet.c:(.text+0x151): undefined reference to `get_CCW_tri_norm'
... и многим другим это нравится. Это все функции, определенные в «vector-f_ops.c»…
/usr/bin/ld: TriNet.c:(.text+0x1abd): undefined reference to `dot_vec4f'
collect2: error: ld returned 1 exit status
make: *** [makefile:50: 01_Planet-Geom] Error 1
У меня есть следующее в «makefile»:
########## COMPILATION SETTINGS ##################
CFLG=-O3 -Wall -std=gnu17
LIBS=-lglut -lGLU -lGL -lm
CLEAN=rm -f *.out *.o *.a
########## DEPENDENCIES ##########################
### Prog Dependencies ###
00_Dyn-6D.o: 00_Dyn-6D.c toolbox.h
01_Planet-Geom.o: 01_Planet-Geom.c toolbox.h geometry.h
### Float Matrix Math ###
matrix4x4f.o: matrix4x4f.c matrix4x4f.h
### OpenGL Toolbox ###
OGL_utils.o: OGL_utils.c toolbox.h
load_assets.o: load_assets.c toolbox.h
vector-f_ops.o: vector-f_ops.c toolbox.h
### Geometry Construction ###
TriNet.o: TriNet.c toolbox.h geometry.h
########## ARCHIVES & GENERAL RULES ##############
toolbox.a: OGL_utils.o load_assets.o vector-f_ops.o
ar -rcs $@ $^
geometry.a: toolbox.a TriNet.o
ar -rcs $@ $^
# Compile rules
.c.o:
gcc -c $(CFLG) $<
########## PROGRAM & CLEAN RULES #################
##### Program Rules ##############################
00_Dyn-6D: 00_Dyn-6D.o toolbox.a
gcc $(CFLG) -o [email protected] $^ $(LIBS)
01_Planet-Geom: 01_Planet-Geom.o toolbox.a geometry.a
gcc $(CFLG) -o [email protected] $^ $(LIBS)
##### Clean Rule #################################
# Clean
clean:
$(CLEAN)
Я дважды проверил, что все исходные файлы имеют соответствующие заголовки.
«TriNet.c» успешно скомпилировался в другом контексте.
Я подтвердил, что #include все еще работает после добавления правил для make 00_Dyn-6D и 01_Planet-Geom.
Также укажите точные сообщения об ошибках. Другими словами, вырежьте и вставьте в вопрос командную строку и получите сообщения об ошибках (если вы получаете тысячи сообщений, вы можете включить только ПЕРВЫЕ сообщения - при компиляции и связывании первые сообщения всегда стоят больше, чем последние сообщения).
В каком файле определяется get_CCW_tri_norm?





Ваша связь не удалась по сочетанию двух причин.
Первый
это:
ar -rcs geometry.a toolbox.a TriNet.o
что является результатом правила Makefile:
geometry.a: toolbox.a TriNet.o
ar -rcs $@ $^
Вы можете поверить, что ar -rcs geometry.a toolbox.a TriNet.o обладает эффектом извлечения
все объектные файлы из архива toolbox.a и добавление их в
целевой архив geometry.a вместе с объектным файлом TriNet.o.
Фактически, он просто архивирует файлы toolbox.a и TriNet.o в
geometry.a, в результате чего этот geometry.a представляет собой архив, содержащий
еще один архив toolbox.a и один объектный файл TriNet.o.
Когда в компоновщик вводится такой архив, как geometry.a, он учитывает только
объектные файлы, являющиеся членами архива, как указано ar t geometry.a.
Он извлечет из архива только те объектные файлы-члены, которые
предоставить определения неопределенных символов ранее в выходном файле и статически
свяжите их с выходным файлом, делая это итеративно, пока архив не даст результат
больше не нужны определения.
Компоновщик не будет рассматривать объектные файлы, являющиеся членами
архивы, входящие в geometry.a. Поэтому что geometry.a может
способствовать вашим ссылкам - это всего лишь TriNet.o, что, конечно, не так
достаточно.
Если вы хотите geometry.a иметь в качестве членов все объектные файлы в toolbox.a
а также TriNet.o то вам нужно будет сделать geometry.a из тех же объектных файлов
который вы поставили в toolbox.a плюс TriNet.o.
Если ar -rcs geometry.a toolbox.a TriNet.o сработало так, как кажется, вы этого ожидаете
to, тогда было бы ненужно связывать geometry.a и toolbox.a в
программы, требующие geometry.a, и вам понадобится какая-то другая причина для toolbox.a
существовать (что, кажется, вы и делаете).
Но, видимо, вы все же считаете необходимым ввести в связку и то, и другое.
вашей программы 01_Planet-Geom.out.
gcc -O3 -Wall -std=gnu17 -o 01_Planet-Geom.out 01_Planet-Geom.o toolbox.a geometry.a -lglut -lGLU -lGL -lm
чья связь не удалась:
/usr/bin/ld: geometry.a(TriNet.o): in function `N_from_VF':
TriNet.c:(.text+0x151): undefined reference to `get_CCW_tri_norm'
Что подводит нас к:
Второй
geometry.a содержит только объектный файл TriNet.o, насколько может видеть компоновщик. Но TriNet.o
содержит неопределенную ссылку на get_CCW_tri_norm, которая (держу пари) определена в члене toolbox.a.
У вас есть ввод toolbox.a для связи, но вы ввели его до geometry.a. Так когда
компоновщик проверил toolbox.a, ему не было известно об отсутствии неопределенной ссылки на get_CCW_tri_norm и
поэтому не искал, не извлекал и не связывал какой-либо объектный файл из toolbox.a, который содержит определение
из get_CCW_tri_norm. Ни один вводимый впоследствии файл не дает такого определения.
поэтому символ остается неопределенным в конце связи.
Файлы, которые вводят в связь неопределенные символы, должны передаются компоновщику перед библиотеками, предоставляющими их определения. Компоновщик проверит библиотеку только для того, чтобы найти определения неопределенных символов, которые уже есть в наличии, и не оглядываться назад.
Спасибо! Соответствующие исправления были: geometry.a: TriNet.oar -rcs $@ $^ и 01_Planet-Geom: 01_Planet-Geom.o geometry.a toolbox.a gcc $(CFLG) -o [email protected] $^ $(LIBS).