Makefile을 만드는 작업이 많이 있는데 다음 파일이 있습니다.
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/boo.c
https://github.com/systems-cs-pub-ro/uso/raw/master/tema1/light.o
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.c
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.h
Makefile을 만들어야 합니다. "실행 파일을 생성 exec
하고 light.o
이전 구현의 sound.o
컴파일 타임에 생성합니다 sound.c
. 명령을 수신하거나 make
파일 make build
을 생성해야 합니다. 필요한 경우 exec
전체 프로그램을 준수하는 Makefile에 규칙을 추가하고 그런 다음 생성한 개체 파일을 삭제하는 규칙을 run
추가하여 실행합니다 . 또한 컴파일 후 중간 파일( , )을 생성하는 규칙을 추가합니다.clean
templates
boo.s
boo.o
boo.c
이건 내 메이크파일이야
build: light.o sound.o
gcc light.o sound.o -o exec
sound.o: sound.c
gcc -c sound.c
templates: boo.c
gcc -c boo.c
gcc -S boo.c
run: exec
./exec
clean:
rm -f sound.o boo.o boo.s exec
하지만 "올바른" 실행 파일을 만들지 않았다는 메시지가 표시됩니다. 제가 뭘 잘못하고 있는 걸까요? 나는 boo.o
exec 파일에 추가해야 한다고 생각하는데, 그렇게 하려고 하면 다음과 같은 결과가 나타납니다 boo.c multiple definition of main light.o:light.c:first defined here
.
답변1
(숙제처럼 들리네요.)
먼저 오류 메시지:
boo.c multiple definition of main
light.o:light.c:first defined here.
이는 함께 연결하려는 파일에 이름이 지정된 함수의 복사본이 여러 개 있다는 것을 의미하는데 main()
, 이는 분명히 잘못된 것입니다.
을 재사용하려고 light.o
하지만 이는 가 아닌 다른 기능이 있는 경우에만 실제로 작동합니다 main()
. 그냥 그렇게 부르자 light()
. 또한 컴파일러가 소스 코드를 보지 않고도 함수의 속성(기본적으로 매개변수 유형과 반환 값 유형)을 알 수 있도록 .h
파일 #include
d가 필요합니다.boo.c
light()
제가 보기엔 귀하의 파일이 과제에서 예상했던 것과 약간 다르게 구성되어 있는 것 같습니다. 교수님이 일련의 상호 연결된 과제를 만들었을 수 있습니다. 시리즈의 이전 과제에서 지름길을 택하면 이전 과제의 코드를 재사용하는 후속 과제가 제대로 작동하지 않습니다.
교수님은 재사용이 가능하도록 코드를 배열하는 방법과 그렇지 않으면 어떻게 되는지 가르치려고 하십니다.
Makefile 규칙의 기본 형식은 다음과 같습니다.
<name of target>: <names of files the creation process depends on>
<command(s) to create the target file>
파일 생성은 .c
파일 자체뿐만 아니라 .h
파일에 포함된 파일에 따라 달라집니다. 일반적으로 시스템에는 파일이 포함되어 있다고 가정할 수 있습니다(포함한 파일은 #include <filename>
변경되지 않으므로 Makefile 규칙에 추가할 필요가 없습니다). 그러나 .h
프로젝트의 일부인 모든 파일도 포함되어야 합니다. .
실제로 파일이 아닌 "가상 대상"이 있을 수도 있습니다. 비슷한 일을 할 수 있게 해줍니다 make clean
. 가상 대상을 다른 대상의 종속성으로 사용할 수도 있습니다. 가상 대상에는 연결된 실제 파일이 없기 때문에 가상 대상이 무언가에 대한 종속성으로 나열될 때마다 가상 대상을 "생성"하는 명령이 실행됩니다. 다른 것을 구축해야 합니다.
또한 명령을 포함하지 않지만 하나 이상의 Makefile 대상을 종속성으로 나열하는 Makefile 규칙이 있을 수 있습니다. 종속성이 하나만 있는 경우 명령이 없는 대상은 종속성으로 나열된 대상의 다른 이름으로 작동합니다. 종속성이 여러 개인 경우 명령 없는 대상은 단일 명령을 사용하여 여러 Makefile 대상을 빌드하는 방법이 됩니다.
build:
교수님께서는 자신의 지시 없이 대상을 만들고 싶어하시는 것 같습니다 . 이는 두 가지 목표에만 의존해야 합니다.
- 실제 실행 파일을 빌드하는 별도의 대상
templates
목표
light.o
소스 코드를 보지 않고 이것이 무엇인지 어떻게 알 수 있는지 궁금할 것입니다. 쉬움 - 나는 당신의 것을 다운로드 light.o
하고 다음 명령을 사용했습니다.
$ readelf -s light.o
Symbol table '.symtab' contains 12 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS light.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 8
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 51 FUNC GLOBAL DEFAULT 1 main
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
11: 00000000 0 NOTYPE GLOBAL DEFAULT UND sound
light.o
이는 이라는 소스 파일에서 light.c
이라는 함수가 정의되고 여기에 정의되지 않은 이라는 함수를 main()
사용한다는 것을 알려줍니다 . 표준 라이브러리에서 제공되지만 완전한 실행 파일을 형성하려면 이 파일과 연결된 다른 파일에서 정의되어야 합니다.puts()
sound()
puts()
sound()