#c #macos #build #makefile #clang
#c #macos #сборка #makefile #clang
Вопрос:
Хорошо, я пытаюсь создать makefile для компиляции программы в разных средах. В Linux (Mint) это работает просто отлично, но в Mac OS я получаю эту ошибку:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [build] Error 1
С помощью ‘-v’:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
"/Library/Developer/CommandLineTools/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.9.0 -w -o bin/Darwin/main ./cfprintf.o ./file.o ./inputmanager.o ./neditfile.o ./neditmanager.o ./neditscreen.o ./n_string.o ./sys_booter.o ./sys_display.o ./sys_manager.o ./sys_screen.o -lc -lSystem /Library/Developer/CommandLineTools/usr/bin/../lib/clang/5.1/lib/darwin/libclang_rt.osx.a
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [build] Error 1
Теперь вот makefile:
CC = clang
LIB =
INC = -I src/
OPTIONS = -w
OBJS = $(shell find ./src/obj -name '*.cpp')
IO = $(shell find ./src/io -name '*.cpp')
SYS = $(shell find ./src/sys -name '*.cpp')
APPS = $(shell find ./src/apps -name '*.cpp')
EXEC = bin/$(shell uname)/main
.PHONY: dummy build all objects io sys apps incBC clear run
build: clear incBC objects io sys apps
@echo "-> Compiling main... "
@$(CC) -c src/main.cpp $(INC) $(OPTIONS)
@echo "-> Building environment... "
@$(CC) $(shell find . -name '*.o') $(LIB) $(OPTIONS) -o $(EXEC) -v
@echo "-> Removing all objects file from compilation... "
@rm *.o
objects:
@echo "-> Building objects files and classes... "
@$(CC) -c $(OBJS) $(INC) $(OPTIONS)
io:
@echo "-> Building input/output files and classes..."
@$(CC) -c $(IO) $(INC) $(OPTIONS)
sys:
@echo "-> Building system files and classes..."
@$(CC) -c $(SYS) $(INC) $(OPTIONS)
apps:
@echo "-> Building all apps files and classes..."
@$(CC) -c $(APPS) $(INC) $(OPTIONS)
incBC:
@echo "-> Updated build count..."
@./incBC.sh
clear:
clear
run:
cd bin/$(shell uname)/ amp;amp; clear amp;amp; ./main
Теперь, что (по крайней мере, для меня) действительно странно, так это то, что когда я печатаю make
, он терпит неудачу один раз из двух… БУКВАЛЬНО один из двух! И когда это не удается, я получаю сообщение об ошибке выше. Что я заметил из этого сообщения, так это то, что в ld
команде нет main.o
, и, вероятно, поэтому я получаю неопределенную ссылку. Мой вопрос: почему? Почему именно один раз из двух и как я могу это исправить?
Ответ №1:
Это странный makefile. Почему бы просто не написать сценарий оболочки? В этом makefile нет ничего, что использовало бы какие-либо преимущества самого make: он всегда будет перестраивать все каждый раз. Смысл написания makefile вместо сценария оболочки заключается в том, чтобы вы могли избежать перестроения объектов, которые не претерпели изменений.
В любом случае, причина, по которой вы видите сбои, заключается в том, что вы используете $(shell ...)
функцию make внутри рецепта. В этом нет необходимости, поскольку рецепт уже запущен в оболочке. Причина, по которой у вас это не получается, заключается в том, что make сначала развернет весь рецепт (все строки), прежде чем запустить ваш рецепт (это должно быть сделано очевидно). Это означает, что, поскольку вы используете $(shell ...)
эту find
команду, она выполняется перед запуском рецепта, а перед запуском рецепта вы не скомпилировали свой main.o
, поэтому find
команда не включает его в список найденных объектных файлов. Затем при следующем запуске он main.o
существует из предыдущего запуска, поэтому find
команда находит его.
Измените эту строку:
@$(CC) $(shell find . -name '*.o') $(LIB) $(OPTIONS) -o $(EXEC) -v
к этому:
@$(CC) `find . -name '*.o'` $(LIB) $(OPTIONS) -o $(EXEC) -v
и это сработает.
Хотя это все еще не очень полезно как makefile.
Комментарии:
1. Спасибо!! Из того, что я прочитал, я полагаю, что мои рецепты (правила, я полагаю) должны иметь вид: ‘***.o:’ чтобы быть более эффективными, а? Тогда, я думаю, это мой следующий шаг! Еще раз спасибо