2017년 1월 22일 일요일
[DB] CentOS7에 Oracle11g r2 설치
http://tocsg.tistory.com/30 <<-- 이걸 중심으로
oracle계정에서 ./runintall 후, KDE에서 한글깨질때
export LANG=C 로 환경변수 변경 후, 다시 실행
http://blog.daum.net/ferrariq/10 <<--- 오라클 설치중에 빠진 lib가 있을경우 ( Prerequisite Checks 단계에서 ) 라이브러 다 설치
라이브러리를 다 설치 한거 같은데도 Prerequisite Checks 단계에서 걸리면 그냥 Continue 버튼으로 계속 설치하게 함.
2017년 1월 16일 월요일
[ Linux ] linux 환경 C 컴파일 과정 & make 의 이해
|
|
|
Name
|
Author
|
|
Current Status
|
1.1
|
Date
|
2014-02-27
|
Version
|
Updates
|
Author
|
Date
|
1.0
|
초안
|
박은탁
|
2014-02-26
|
1.1
|
3.3.4 확장자 규칙 추가
3.3.4 와일드 카드 매칭 기법과 대입 참조 기법 추가
|
|
2014-02-27
|
|
|
|
|
1.1.
컴파일이란?
흔히 말하기를 컴파일은 인간이 이해할 수 있는 형식언어로 작성된 소스 코드를
CPU가 이해할 수 있는 기계어로 번역하는 과정. 결국,
컴파일이라는 것은 결국 컴파일러를 이용해 인간이 만든
코드를 CPU가 이해할 수 있는 코드로 변경하는 과정이다.
1.1.1.
기계어
기계어를 다른
말로 머신 인스트럭션(machine instruction) 이라고 한다.
이런 인스트럭션은 01010101 같은 이진수로 이뤄진 숫자로 cpu종류마다 고유하며, cpu가 특정 행동을 취하게 하기 위한 코드를
말한다.
각각의 인스트럭션은 어셈블리 코드와 1:1 대응하므로 숫자로 이뤄진
인스트럭션을 역어셈블해 어셈블리언어로 표현할 수 있고, 어셈블리 언어를 어셈블해 인스트럭션으로 표현할
수 있다..
1.1.2.
용어
*전처리기
원시파일 내의 모든 전처리기 지시자를 컴파일 할 수 있는 C의 문장으로
전개하는 작업을 담당.
*어셈블러
어셈블러는 기본 컴퓨터 명령어들을, 컴퓨터 프로세서가 기본 연산을
수행하는데 사용할 수 있는 비트 패턴으로 변환시키는 프로그램이다.
*링크(Linking)
오브젝트 파일을 필요한 라이브러리와 연결시켜(링크) 컴퓨터가 알 수 있는 기계어로 바꾼다. 그러면 실제로 실행 가능한
파일을 생성하게 된다
2.
C 소스 Complie 과정
2.1.
gcc 컴파일러
gcc는 GNU Compiler
Collection C컴파일러인 gcc 와 C++, 자바등의
컴파일러들을 포함하는 컴파일러의 묶음을 의미한다.
소문자 gcc는 GNU C
Compiler를 의미하고 대문자 GCC 는 GNU
Compiler Collection의 약자로 C컴파일러인
gcc 와 C++, 자바 등의 컴파일러들을 포함하는 컴파일러의 묶음을 의미한다.
usr/bin/gcc는 내부적으로 전처리기인 cpp0(C++ 전처리기)또는
cc1 –E(C 전처리기)명령을 호출해 전처리 과정을 수행하고, 진짜 C컴파일러인 cc1(C언어
컴파일러)또는 cc1plus(C++ 컴파일러)를 호출해 컴파일한 후 어셈블러인 as를 호출해 목적 코드를 만들고, 마지막으로 링커를 호출하는 collect2를 호출하여 collect2가 내부적으로 링커인 id를 호출해 라이브러리와 링크해
실행 파일로 만들어낸다.
gcc는 실제 컴파일 과정을 담당하지 않고, 전처리기와 C컴파일러, 어셈블러, 링커를 각각 호출해 주는 역할만 담당한다. 이렇게 각각의 컴파일
과정에 필요한 명령을 순차적으로 호출해 주는 것을 컴파일러 드라이버라고 부른다.
Gcc 컴파일러 드라이버 내에 컴파일러 들
|
|
cc1
|
C 컴파일러, -E 옵션 을 붙이면 C 전처리기로 동작
|
Cc1plus
|
C++ 컴파일러, -E 옵션 을 붙이면 C++ 전처리기로 동작
|
Collect2
|
링커(내부에서 링커인 id를 호출해 링크함)
|
…
|
|
2.2.
gcc compile 과정
1. gcc는 cc1 –E를 호출해 전처리 과정을 거쳐 like.c 파일을 like.i 파일로 만든다.
2. like.i 파일은 C 컴파일러인 cc1에 의해 어셈블리 코드인 like.s로 컴파일된다.
3. like.s는 as 어셈블러에
의해 어셈블 과정을 거쳐 like.o 오브젝트 파일로 만들어진다.
4. like.o 파일은 다시 collec2가
링커인 id를 호출한 후 표준 C라이브러리와 링크함.
5. 최종적으로 실행파일 like 가
만들어진다.
2.2.1.
gcc compile test -
like.c 파일 컴파일 수행
like.c 소스 파일 내용
|
#include <stdio.h>
int main()
{
printf("I like you!\n");
return
0;
}
|
[euntark@devweb ~]$ gcc -v -save-temps -o like
like.c
『-v : 컴파일 과정을 화면에 출력
-save-temps :
컴파일 과정에서 발생되는 중간 파일을 지우지 않고 저장
-o : 컴파일된 파일명을 like로 하라는 의미 』
|
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr
--mandir=/usr/share/man --infodir=/usr/share/info --enable-shared
--enable-threads=posix --enable-checking=release --with-system-zlib
--enable-__cxa_atexit --disable-libunwind-exceptions
--enable-libgcj-multifile
--enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk
--disable-dssi --disable-plugin
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic
--host=i386-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)
/usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1
-E -quiet -v like.c -mtune=generic -fpch-preprocess -o like.i
ignoring nonexistent directory
"/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/gcc/i386-redhat-linux/4.1.2/include
/usr/include
End of search list.
/usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1
-fpreprocessed like.i -quiet -dumpbase like.c -mtune=generic -auxbase like
-version -o like.s
GNU C version 4.1.2 20080704 (Red Hat 4.1.2-50)
(i386-redhat-linux)
compiled by GNU C version 4.1.2 20080704 (Red Hat 4.1.2-50).
GGC heuristics: --param ggc-min-expand=100 --param
ggc-min-heapsize=131072
Compiler executable checksum:
d8d95095eb3c93dae4bed2137d559f95
as -V -Qy -o
like.o like.s
GNU assembler version 2.17.50.0.6-14.el5
(i386-redhat-linux) using BFD version 2.17.50.0.6-14.el5 20061020
/usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2
--eh-frame-hdr -m elf_i386 --hash-style=gnu -dynamic-linker
/lib/ld-linux.so.2 -o like
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o
/usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o
-L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2
-L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.. like.o -lgcc --as-needed
-lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o
|
생성 확인
|
ASP50
asp40 hello_dir like
like.i like.s ppurio50
vhosts.conf
asp20
hello_cp.txt hello_mv.txt like.c like.o ppurio30
test1
|
3. Make
3.1.
Make의 이해
make는 파일 관리 유틸리티다.
make는 각 파일 간의 종속 관계를 파악해 기술 파일(make file)에 기술된 대로
컴파일 명령이나 shell명령을 순차적으로 내린다. make는
각 파일에 대한 반복적 명령을 자동화시켜 개발자의 수고를 덜고, 시간을 절약 할 수 있다.
make의 동작 방식은 매우 단순하다. makefile 기술 파일을 작성하면 make가 기술 파일에 적힌
대로 명령을 수행한다. 결국 기술 파일을 작성하는 법과 make에
대한 몇 가지 특징만 이해하면 make를 프로젝트에 도입할 수 있다.
3.2.
예제-Make 기본 동작 이해
3.2.1.
예제 소스
예제 소스 파일 내용
|
|
diary.h
#include<stdio.h>
int main();
int calendar();
|
memo.c
#include "diary.h"
int memo()
{
printf("function memo.\n");
return
0;
}
|
calendar.c
#include "diary.h"
int calendar()
{
printf("function calendar.\n");
return
0;
}
|
main.c
#include "diary.h"
int main()
{
memo();
calendar();
return
0;
}
|
3.2.2.
예제-make 파일 생성
Makefile의 내용
|
||
all : diary
diary
: memo.o calendar.o main.o
gcc -W -Wall -o diary memo.o
calendar.o main.o
memo.o : memo.c
gcc -W
-Wall -c -o memo.o memo.c
calendar.o : calendar.c
gcc -W
-Wall -c -o calendar.o calendar.c
main.o : main.c
gcc -W
-Wall -c -o main.o main.c
clean :
rm -rf *.o diary
|
||
-o : 출력 파일명을 지정할 때 사용합니다.
-c : 링킹 과정을 진행 하지 않고
.o 파일인 오브젝트 파일까지만 생성 하게 됩니다.
-Wall : 모든 모호한 코딩에 대해서 경고를 보내는 옵션
-W : 합법적이지만 모호한 코딩에 대해서 경고를 보내는 옵션
-W -Wall : 아주 사소한 모호성에 대해서도 경고
|
3.2.3.
make명령으로 컴파일 수행
Make 명령을 내리면 각 오브젝트에 대한 컴파일 명령을 수행한 후 최종적으로 diary 실행 파일을 생성한다.
|
[euntark@devweb
maketest]$ make
gcc
-W -Wall -c -o memo.o memo.c
gcc
-W -Wall -c -o calendar.o calendar.c
gcc
-W -Wall -c -o main.o main.c
gcc
-W -Wall -o diary memo.o calendar.o main.o
|
3.2.4.
생성된 파일 목록
생성한 파일
목록
|
calendar.c
diary.h main.c makefile
memo.c
|
3.2.5.
컴파일 후 최종 생성된 파일 목록
컴파일 후 생성된 파일 목록
|
calendar.c calendar.o diary diary.h
main.c main.o makefile memo.c
memo.o
|
3.2.1.
예제-make기본동작 수행 순서
make의 기본동작순서는
1)make 명령을 내리면 make는 먼저 현재 디렉토리 내에서 기술 파일을
찾는다. 기술 파일은 makefile이다.
2)makefile 내에서 제일 처음 오는 타겟을 찾는다.(위의 예제 all 타겟)
3)해당 타겟을 만들기 위한
종속 항목을 보고(예제 diary)파일이 현재 디렉토리내에
없다는 것을 확인하다.
4)diary를 생성하기 위한 룰을 찾기 위해 diary타겟의 종속 항목을
접하고 첫 종속항목(memo.o)이 아직 만들어져 있지 안았음을 확인하다.
5)memo.o를 생성하기 위한 룰을 찾기 위해 memo.o 항목을 읽고
종속 항목 memo.c 가 현재 디렉토리 내에 있는 것을 확인하면
make는 memo.o를 만들기 위해 아래 명령으로
memo.o를 컴파일 해 만들어낸다. 만약 memo.o가
미리 만들어져 있다면 make는 다시 만들 필요가 있는지 검토한다. 만들어져
있는 memo.o보다 memo.c의 수정시간이 최근이라면 memo.o가 만들어진 후 memo가 수정되었기 때문에 다시 만들
필요가 없다. 다시 만들어야 할 필요가 있으면 make는
아래 명령을 수행하고 그렇지 않으면 명령을 건너 뛰고 다음 과정을 수행한다.
6)다시 diary 타겟의 종속항목으로가 memo.o는 만들어 졌지만, calendar.o는 아직 생성 되지 않음을 확인하다.
7)calendar.o와 main.o 도 5) ~6) 반복
8)이제는 diary를 생성하기 위한 종속 항목임 3개의 파일이 다 만들어진
것을 확인하고 diary를 생성하기 위한 명령을 수행해 dirary를
생성한다.
9)all 타겟으로 가서 생성하기 위한 diary가 만들어진 것을 확인한
후 현재 all 타켓을 생성하기 위한 특별한 명령이 없으므로 make는 all타겟이 생성 되었다고 간주하고 종료.
3.3.
기술 파일(make file) 작성
3.3.1.
기술 파일의 기본 구조
매크로 정의
CC=gcc
룰1
Target1 :dependency1 dependeny2 …
명령1
[
TAB ] command1
[
TAB ] command2
…..
룰N
TargetN :dependencyN dependenyN+1 …
명령2
[
TAB ] commandN
[
TAB ] commandN+1
….
|
3.3.2.
기술 파일의 구문 작성 기본 규칙
1. 명령의 시작은 반드시 TAB으로 시작되어야 한다.
2. 비어 있는 행은 무시된다.
3. ‘#’을 만나면 개행 문자를 만날 때까지 무시한다.
4. 기술 행이 길어지면 ‘백슬레쉬’를 사용해서 이을 수
있다.
5. ‘;’는 명령 라인을 나눌 때 사용 한다.
6. 종속 항목이 없는 타겟도 사용 가능하다.
7. 명령 부분에는 어떤 명령이 와도 상관없다.
3.3.3.
매크로 사용
기술 파일 내에 매크로는 C와 마찬가지로 사용자 정의 변수에 특정한
문자열을 정의하고 표현하는 것을 의미한다.
CC=gcc
|
CC매크로를
정의했다면 CC는 기술 파일 내부에서 $(CC)로 표기함으로
써 gcc로 치환될 수 있다.
3.3.3.1.
매크로 기본 규칙
1.
매크로의 정의는 ‘=’를 포함하는 하나의 문장이다.
‘=’의 좌측에는 매크로 이름이 오고 우측에는 정의 문자열이 온다.
2.
‘#’은 주석문의 시작이다.
3.
여러 행을 사용할 때는 ‘백슬레쉬’를 사용한다.
4.
매크로를 참조할 때는 괄호나 중괄호를 둘러싸고 앞에 ’$’를
붙인다.
5.
정의 되지 않는 매크로를 참조할 때는 null 문자열로
치환된다.
6.
중복된 정의는 최후에 정의된 값을 사용한다.
7.
매크로 정의 시 이전에 정의된 매크로를 참조해 정의할 수 있다.
8.
여러 대입 기법을 사용할 수 있다.
NAME1 =string #재귀적 확장 매크로
NAME2 :=string #단순 확장 매크로
NAME2 +=string #기존의 매크로에 공백을 두고 현재의
문자열을 덧붙인다.
NAME3 ?=string #현재 정의하는 매크로가 정의되어 있지
않았다면 치환 하고 이전에 매크로가 정의 되어 있으면 이 치환은 무시한다.
3.3.3.2.
매크로 사용시 주의 사항.
1. 구분을 위해 문자열에 따옴표를 넣으면 따옴표 또한 문자열의
일부로 인식한다.
2. 매크로의 이름에는 ‘:’
, ’=’ , ‘#’ 이 들어 가서는 안되고 TAB으로 시작해서도 안 된다. (TAB으로 시작하는 라인은 명령라인으로
인식하기 때문에)
3. 매크로는 반드시 치환될 위치보다 먼저 정의 되어야 한다
3.3.3.3.
매크로 규칙 적용 makefile
매크로 규칙에 유통적으로 직관적이게
고친 예제 makefile
|
||
CC
= gcc
CFLAGS
= -W –Wall
TARGET
= diary
all
: $(TARGET)
$(TARGET) : memo.o
calendar.o main.o
$(CC) $(CFLAGS) -o $(TARGET) memo.o
calendar.o main.o
memo.o
: memo.c
$(CC) $(CFLAGS) -c -o memo.o memo.c
calendar.o
: calendar.c
$(CC) $(CFLAGS) -c -o calendar.o
calendar.c
main.o
: main.c
$(CC) $(CFLAGS) -c -o main.o main.c
clean
:
rm -rf *.o diary
|
3.3.3.4.
내부적으로 정의 되어 있는 매크로
make
–p 명령을 쉘에서 내리면 make 내부에 정의된 매크로 리스트들이 나열된다.
매크로 이름
|
설명
|
기본값
|
AR
|
아카이브 관리 프로그램
|
ar
|
AS
|
어셈블러
|
as
|
CC
|
C 컴파일러
|
cc
|
CXX
|
C++컴파일러
|
g++
|
CO
|
RCS
checkout 프로그램
|
co
|
CPP
|
C 전처리기
|
cc –E
|
FC
|
포트란 컴파일러
|
f77
|
GET
|
SCCS 관련 프로그램
|
get
|
LD
|
링크
|
ld
|
LEX
|
스캐너 코드 생성기
|
lex
|
PC
|
파스칼 컴파일러
|
pc
|
YACC
|
파서 코드 생성기
|
yacc
|
MAKEINFO
|
Texinfo 파일을 Info 파일로 변환
|
makeinfo
|
TEX
|
TeX 문서로부터 TeX
DVI 생성
|
tex
|
TEXI2DVI
|
Texinfo 파일을 dvi 파일로 변환
프로그램
|
texi2dvi
|
WEAVE
|
Web을 TeX로 변환
|
weave
|
CWEAVE
|
C
Web을 TeX로 변환
|
cweave
|
TANGLE
|
Web을 파스칼로 변환
|
tangle
|
CTANGLE
|
C
Web을 C로 변환
|
ctangle
|
RM
|
파일을 지우는 명령
|
rm –f
|
ARFLAGS
|
ar 플래그
|
rv
|
ASFLAGS
|
어셈블러 플래그
|
|
CFLAGS
|
C 컴파일러
플래그
|
|
CXXFLAGS
|
C++ 컴파일러
플래그
|
|
COFLAGS
|
RCS
co 플래그
|
|
CPPFLAGS
|
C 전처리기
플래그
|
|
FFLAGS
|
포트란 컴파일러 플래그
|
|
GFLAGS
|
SCCS
get 플래그
|
|
LDFLAGS
|
링크 플래그
|
|
LFLAGS
|
Lex 플래그
|
|
PFLAGS
|
파스칼 컴파일러 플래그
|
|
YFLAGS
|
Yacc플래그
|
|
3.3.3.5.
자동 매크로
$?
|
-현재의 타겟보다 최근에 변경된 종속 항목 리스트
(확장자
규칙에서는 사용 불가)
|
$^
|
- 현재 타겟의 종속 항목 리스트
(확장자
규칙에서는 사용 불가)
|
$@
|
-현재 타겟의 이름
|
$<
|
-현재 타겟보다 최근에 변경된 종속 항목리스트
(확장자
규칙에서만 사용 가능)
|
$*
|
-현재 타겟보다 최근에 변경된 현재 종속 항목의 이름
(확장자제외)
(확장자
규칙에서만 사용 가능)
|
$%
|
-현재의 타깃이 라이브러리 모듈일 때 .o 파일에 대응되는 이름
|
3.3.3.6.
자동매크로를 적용한 makefile.
자동 매크로를 이용한 makefile
|
CC = gcc
CFLAGS = -W -Wall
TARGET = diary
all : $(TARGET)
$(TARGET) : memo.o calendar.o main.o
$(CC)
$(CFLAGS) -o $@ $^
memo.o : memo.c
$(CC)
$(CFLAGS) -c -o $@ $^
calendar.o : calendar.c
$(CC)
$(CFLAGS) -c -o $@ $^
main.o : main.c
$(CC)
$(CFLAGS) -c -o $@ $^
clean :
rm -rf *.o diary
|
3.3.4.
확장자 규칙
컴파일러는
확장자를 보고 어떤 프로그래밍 소스파일인지 인식한다.
3.3.4.1.
내부 정의 확장자 규칙
%.o:
%.c
# 실행할 명령어 (내장) : $(COMPILE.c) $(OUTPUT_OPTION) $< %.o: %.f # 실행할 명령어 (내장) : $(COMPILE.f) $(OUTPUT_OPTION) $< %.o: %.S # 실행할 명령어 (내장) : $(COMPILE.S) -o $@ $<
…
|
- %는 일치하는 확장자를 제외한 파일명을 의미한다.
- gcc 컴파일러는 *.c 파일이 있을 때 확장자 .c를 보고 그 파일이 C 프로그래밍 소스 파일인 것을 인식한다. - COMPILE.xx : 컴파일러 및 컴파일 옵션을 지정 - OUTPUT_OPTION : -o $< 로 지정
*.c 파일은 C컴파일러를 이용해 *.o 파일로 만들 수 있고, *.f 파일은 포트란 컴파일러를 이용해 *.o 파일을 만들 수
있다.
이런 확장자가 가지는 규칙에 기초해 make는 사용자가 내리는 명령을 알아서 해석해 컴파일 과정을 자동화할 수 있다.
|
3.3.4.2.
내부 정의 확장자 규칙 적용 makefile & 설명
내부 정의 확장자 규칙 이용한 makefile
|
OBJECTS = memo.o calendar.o main.o
all : diary
diary : $(OBJECTS)
$(CC) -o $@ $^
clean :
rm -rf *.o diary
|
내부 정의 확장자 규칙 이용한 makefile 컴파일 화면
|
[euntark@devweb
maketest]$ make
cc -c -o memo.o memo.c
cc -c -o calendar.o calendar.c
cc -c -o main.o main.c
cc -o diary memo.o calendar.o
main.o
|
위와 같은 기술 파일을 make는 다음 과같이 해석해 명령을 수행한다.
1.
기술 파일에서 diary를 생성하기 위해 make는 종속 항목을 살펴보고 종속 항목을 각각 타겟으로 설정한다.
2.
diary는
memo.o에 의존하고 memo.o는 만들어지지 않았으며
memo.o를 생성하기 위한 룰도 기술 파일에는 정의되어 있지 않다.
3.
make는 확장자가 .o인 내부 확장자 규칙을 이용해 다음과 같은 기준으로 현재 디렉토리에서
memo.o를 생성할 파일을 찾는다.
-확장자를 제외하고 memo.o와
같은 이름이어야 한다.
4.
내부 정의 확장자 규칙의 기술된 명령을 수행하여 컴파일을 수행한다.
3.3.4.2.1. make 유틸리티의 디폴트 처리 방식
- 타겟과 종속성은 있지만 함께 기술했던 명령어가 없이도 make 유틸리티가 스스로 알고 있다.
- make
유틸리티의 디폴트 처리 방식 :
${CC} ${CFLAGS} -c -o $@ $*.c
- make
유틸리티는 종속성에 의해 .o를
확장자로 하는 타겟을 만날 때마다 이 명령어에 대입한다.
3.3.5.
와일드 카드 매칭 기법과 대입 참조 기법
와일드 카드 매칭 기법과 대입 참조
기법을 적용한 makefile
|
SRCS =$(wildcard *.c) # memo.c calendar.c main.c
OBJECTS=$(SRCS: .c=.o) # memo.c calendar.c main.c
all : diary
diary : $(OBJECTS)
$(CC) -o $@ $^
clean :
rm -rf *.o diary
|
SRCS 매크로에서
$(wildcard *.c)는 현재 디렉토리에서 *.c 와 파일명이 일치하는 파일을 찾아
공백을 구분 문자로 SRCS 매크로에 정의한다.
결국 SRCS에는 현재 디렉토리에 있는 memo.c calendar.c main.c로 정의된다.
정의된 SRCS는 다시
OBJECTS 매크로에 정의 되는데, $(SRCS: .c=.o)와 같은 대입 참조 기법을
통해 확장자가 .c 가 .o로 바뀐다. 그래서 memo.c calendar.c main.c로 정의된다.
위 기술 파일에서 SRCS=*.c 라고 하지 않은 이유는 매크로를
정의할 때는 와일드 카드 확장이 되지 않기 때문이다.
*.c 식의 와일드카드 확장은 타겟 정의절과 명령절에서만 일어난다.
그래서 SRCS 매크로는
memo.c calendar.c main.c가 정의되는 게 아니라 *.c가
정의 되기 때문에 OBJECTS 역시 *.o로 정의된다.
$(wildcard *.c)와 같이 사용하는 것을 make로 함수의 사용이라고 한다.
또 다른 make함수
patsubst를 사용하여 한 라인 으로 정리 할 수도 있다.
OBJECTS=$(patsubst %.c %.o $(wildcard
*.c))
세 번째 인자로 오는 $(wildcard)의 결과를 공백으로 구분된
문자열들 각각에 대해 첫 번째 인자인 %.c와 매칭되는 것을 %.o로
바꾼다.
3.3.5.1.
참고 echo $?
셸에서 바로 직전 명령 수행 후 리턴 값을 보려면 echo $? 명령으로
확인 할 수 있다. 0이면 정상적으로 수행 O, 0이 아니면 정상적으로 수행 X
피드 구독하기:
글 (Atom)