레이블이 Make인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Make인 게시물을 표시합니다. 모든 게시물 표시

2/28/2016

autoconf automake aclocal, autoheader,

최근들어 Autoconf와 Automake 및 관련사항을 잘 다루지 않으며, 거의 사실 사용할 일이 없어, 아래와 같이 Link만 연결한다.

  • Autoconf Manual
  https://www.gnu.org/software/autoconf/manual/autoconf.html

2/14/2016

GNU Make 사용법 및 다양한 규칙

1. GNU Make의 Manual 

개발자라고 하면, Make를 모르는 사람이 없을 것이지만, 직접 Makefile을 처음부터 작성해야하는 일은 요즘 드문일 같다.
하지만, Makefile을 수정해야하는 일과 간혹은 처음부터 만들어야 하는 경우가 존재하며,
그때마다 opensource의 Makefile 파일을 참조하면서 보게 되지만, 매번 Makefile을 작성하기가 힘이 든다. 그래서 아래와 같이 정리하고 한다.

보통 Linux에서는 GNU Make사용하지만 다른 플랫폼에서 사용되는 Make와 완벽하게 호환이 된다고 착각하지 말기 바란다.
기본규칙과 GNU Make 내부 규칙을 가급적 분리해서 알아야 두면 편하다.

2.  Make의 기본구성 및 구조 

GNU Make or Make의 기본구성은 3가지로 구성 되며, 각 용어와 구성내용을 알아보자.
Makefile 분석을 하면 항상 기본형태는 아래와 같이 구성이 되며, 세부내용들은
천천히 메뉴얼과 함께 봐야할 부분들이다.

  • targets :  targets 으로 말하며, file name도 있으며, 일종 함수 같은 존재
  • prerequisites : 현재 targets의 recipe를 실행하기전에 다른 targets 들을 순차적으로 호출 
  • recipe : 실제 동작하는 기능이며, command 및 shell script 내부구현.  

targets : prerequisites     
        recipe
        …
# prerequisites는 스페이스로 구분자를 사용한다. 

targets : prerequisites ; recipe        
        recipe
        ....
# 세미콜론은 prerequisites 의 종료를 의미한다.

  • Simple Test Example 
다음은 내가 TEST 하기 위해 만든 간단한 예제이며, 각 내용을 주석으로  #로 표시하고  정리했다.

TARGET = MainTest            # Makefile안에 변수가 사용이 가능
                             # 변수는 암묵적으로 사용가능한 변수도 존재 CFLAGS, LDFLAGS

OBJS = tst1.o tst2.o         # tst1.o tst2.o  tst1.c와 tst2.c의 filname이며, target 지정가능
                             # Make 내부에 기본적으로 설정된 규칙이 있으며, SUFFIX 및 PATTERN에 의해 변경가능    
                             # 작성자가 규칙과 세부설정을 선언하지 않았다면 기본규칙처리

# make를 실행하면 기본으로 all이 실행된다. 

all: $(TARGET)

# $(OBJS)는 prerequisites들 중 하나이므로 먼저 실행 한다 .  최종 $(TARGET) 실행한다.  
# 
 
$(TARGET): $(OBJS)
        @echo ---------------------------------      
        @echo     Test Result Program
        @echo ---------------------------------
        @echo $?
#
# $? 는 The names of all the prerequisites 이므로, tst1.o , tst2.o 출력 
#

clean:
        @rm -rf *.o

#  @ 는 echo의 실행화면을 감춘다. 


  https://www.gnu.org/software/make/manual/html_node/Rule-Syntax.html#Rule-Syntax


2.1 Make의 기본구성의 규칙

Make의 Rule은 위에서 언급한 target prerequisites recipe 의 다양한 기능과 구조를 익히면될것 같다.

자세한 내용은 아래의 링크된 Manual을 참조

  • target 의 다양한 기능 
target 는 wildcard 와 변수도 사용가능하며, 다중 target 등에 다양하게 사용이 가능하다.
target의 특정목적의 target도 존재하니 이부분도 익혀두자.

  • prerequisites의 기능 및 자동기능 
기본적으로 두가지 Type의 기능이 존재하며, '|'로 이를 구분한다.

normal-prerequisites | order-only-prerequisites


1. normal-prerequisites 
target 보다 먼저 순서적으로 prerequisites 진행하지만, 종속적인 관계를 유지하고
prerequisites가 target 보다 시간적으로 새거라면  현재 target은 쓸모가 없어지고 동작되지 않는다.
쉽게말해서 빌드 할경우 수정하지 않은 파일을 빌드하지 못하게하는 기능이라고 생각하면된다.
위에서 의 기준은 항상 시간이며, 빌드를 할 경우 수정된 시간은 Make에게 중요하게 영향을 미친다.


2. order-only-prerequisites
위와 상관없이 강제로 순서대로 실행하는 방법이다.


  https://www.gnu.org/software/make/manual/html_node/Rules.html#Rules
  http://korea.gnu.org/manual/4check/make-3.77/ko/make_4.html#SEC19

  • recipe 의 규칙 
recipe의 기본 rule인 tab 과 항상 시작하는 것이고 중요한 것은 재귀용법인 것 같다.
그리고, 이부분이 핵심이기에 이 부분은 따로 분리해서 설명하겠다.

  https://www.gnu.org/software/make/manual/html_node/Recipes.html#Recipes


2.2 Make의 기본규칙 

Make의 기본구성과 그 사용법을 알았으니, 자세한 동작방식에 대해 알아보자
이를 알아보려면, Make 내부에서 암묵적으로 사용하되는 변수들을 알아야한다.

  • Make 내부에서 Filename에서 wildcard 사용법  
Make의 내부에 기본 wildcard 사용법을 익혀보자, '*' 와 '?' 사용이 주가 될것 같다.
주의사항이 이 내용은 filename에만 적용이 되고, shell에 의존적이다.

TEST를 위해 아래와 같이 구성했다

$ ls
Makefile  build  clean  cst.c  dst.c  est.c  print1  tst1.c  tst11.c  tst2.c  tst22222.c  tst3.c  

// *.c 는 전부 동일한 file 로 구성, build  clean print1diretory 이는 PHONY Target을 테스트

$ cat tst1.c // 전부 동일한 file들 

#include

int test01()
{
 printf("TEST 01  \n");
 return 0;
}


$  vi Makefile 

all: build

## filename or directory 와  구분 및 성능 향상이용  
.PHONY: print1 print2 print3 build clean

### 규칙에 적용될 filename 
SRC1 = *.c              ## wildcard '*' , 모든 filename 
SRC2 = $(wildcard *.c)  ## Make 내부함수이용 $(SRC1) 동일 
SRC3 = tst?.c           ## wildcard '?' , filename 중 한 charter 선택 
SRC3 ?= cst*.c          ## SRC3 변수가 선언이 안되었다면 설정이 된다.  

SRC5 += $(SRC3) est*.c
SRC6 += $(SRC3) dst*.c

# 고급스럽게 ,shell 이용해보자. 
FILES := $(shell echo *.c)

# build를 하기 위해서 모든 *.c를 *.o로 변경 
# 아래와 같이 $(var)에서 pattern을 replaements로 변경한다. 
# $(wildcard *.c) 모든 *.c를 에서 %.c ->%.o 로 변경  
#
# $(patsubst pattern,replacement,$(var)) 

OBJS = $(patsubst %.c,%.o,$(wildcard *.c))  # *.c를 *.o로 변경 

## wildcard '*' , 모든 filename 
clean:
        @rm -f *.o  

# print1 과 print2 는 결과 동일 
print1: ${SRC1}
        @echo $?

print2: ${SRC2}
        @echo $? 
#       @cat $? 

# tst1.c tst2.c tst3.c
print3: ${SRC3}
        @echo $? 
#       @cat $? 

# tst1.c tst2.c tst3.c est.c  
print4: ${SRC5}
        @echo $? 

# tst1.c tst2.c tst3.c dst.c  
print5: ${SRC6}
        @echo $?

# print1,2와 동일 
files: ${FILES}
        @echo $?

# buld *.o로 변경이 되었기 때문에 build 
build: ${OBJS}
        @echo $?  

  https://www.gnu.org/software/make/manual/html_node/Wildcards.html#Wildcards


  • 기본예제 
Makefile의 간단한 예제이며, 사용하기 쉬운 기본예제
  https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-7.html


  • 에러처리  (중요)
Makefile을 만들다 보면 분명 에러가 발생한다 아래의 사이트를 참고해보자.
많은도움을 받는다.
  https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-8.html


  • Make 의 변수 설정 및  추가 
  https://www.gnu.org/software/make/manual/html_node/Setting.html#Setting 
  https://www.gnu.org/software/make/manual/html_node/Appending.html#index-appending-to-variables
  https://www.gnu.org/software/make/manual/html_node/Shell-Function.html#Shell-Function

  • Make 의 Automatic Variables (자동변수)

공통된 규칙은 '$'로 시작이되며, target과 prerequisites 을 기준으로 이 변수를 사용을 한다.
사용되는곳은 recipe에서 주로 적용하여 사용한다.
사실 매번 사용법을 잊어버려 Manual을 보기때문에, 자세한 내용은 Manual을 보자.
주의사항은 prerequisite은 동작모드가 2가지 모드이니 이부분을 잘 이해하고 보기바란다.

  1. $@  : The file name of the target of the rule. (반드시 알아두자)
  2. $%  : The target member name
  3. $?  : The names of all the prerequisites
  4. $<  : The name of the first prerequisite
  5. $|  : The names of all the order-only prerequisites

  https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables


  • Make의 Special Target 
Make내부에서 사용되는 특별한 Target이며, 선언하여 이를 사용한다.
많이 사용되는 것 두개를 다루면 다른 Special Target은 Manual 참조

.POHNY :  target 과 filename을 구분과 성능향상을 위해서 사용

 상위에서도 간단하게 작성했지만, target의 이름과 동일한 filename or directory가 존재한다면, 
make가 문제가 생긴다. 이를 방지하고자 사용하며, 이를 이용하면, 이를 체크할 필요가 없기에 성능이 향상이 된다.  

.SUFFIXES : The prerequisites of the special target, 즉  prerequisites의 접미사 규칙

.SUFFIXES : .c .o
.SUFFIXES : .cpp .o     ## 본인이 정의 하면 된다. 

.c.o:           ## 이와 같이 직접 정의 해줘도 정의 해줘도 되며, 세부설정이 가능하다. 
        $(CC) $(CFLAGS) $(INC_DIR) -c $<


  https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets
  https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-3.html


  • Make의 빌드에 관련된 변수 (Implicit-Variables)
Make 내부에는 묵시적으로 빌드에 관련된 설정 및 옵션이 정해져 있지만 이를 본인 변경이 가능하다.
특히 임베디드에서는 이부분을 별도로 설정을 해야한다.

  https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html#Implicit-Variables

  • Make의 Pattern Rule  
Make 내부에는 묵시적으로 정해진 Pattern 규칙이 존재하지만, 이를 변경을 해야하는 경우가 많이 발생한다.
정확히 말해 Suffix 의 Pattern을 변경할때 필요하다. 

2.3 Make의 기능의 확장 

상위에서도 간단하게 사용했지만, GNU make 내부에 함수가 존재하며, 아래와 같이
이를 이용하면 편한하게 Make 작성이 가능하다.

  • Make 내부 안에서 사용가능한 함수 (중요)
  Make 내부에서 사용가능한 Macro 같은 함수로 다양한 함수를 제공하고 있다.

$(subst from,to,text)  // 대체하는 함수 

$(subst ee,EE,feet on the street)     //  fEEt on the strEEt’, ee->EE 대체 

$(filter pattern…,text) // filter 역할함수

sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
        cc $(filter %.c %.s,$(sources)) -o foo       // foo.c bar.c baz.s 만 빌드 

$(foreach var,list,text)  // shell script의 반복문과 유사하다 , text는 결과로 생각하면 되겠다. 

dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))   // a/* b/* c/* /d* 


  https://www.gnu.org/software/make/manual/html_node/Functions.html#Functions


  • Make 내부의 조건문 (변수와 함께 사용)

ifeq ($(CC),gcc)
        $(CC) -o foo $(objects) $(libs_for_gcc)
else
        $(CC) -o foo $(objects) $(normal_libs)
endif


  https://www.gnu.org/software/make/manual/html_node/Conditionals.html#Conditionals
  https://www.gnu.org/software/make/manual/html_node/Conditional-Example.html#Conditional-Example
  https://www.gnu.org/software/make/manual/html_node/Conditional-Syntax.html


3.  Make의 recipe 구현 

make의 recipe는 실제의 동작이며, 가장 중요한 부분이기에 어떻게 사용할 것인지,
응용은 어떻게 할것인지에 대해 좀 자세히 알아보자

3.1 recipe의 Linux command 적용 

Linux 내부에서 사용되는 다양한 command를 이용하여, Make 에 적용하는 방법이다.
가장 많이 사용하는 command를 아래와 같이 구성했으며, 이를 보고 간단히 구현을 해보자.

@는 command의 실행을보여주지 않는다.
`` 먼저 이 command를 실행한 후 결과를 연결해준다. (파이프 개념)  (stdout -> stdin)
 export를 이용하여 변수에 할당 및 변수값 조정을 했었는데, 이부분은 지금 힘든것 같다.
(다른방법으로 찾아보자, 가능하면 user mode에서 해결하자 )

 $ vi Makefile 
test:
        @echo     finished sub direcory 
clean:
        @rm -rf *.o
install:
        install -d $(DESTDIR)   ## 존재하지 않는 디렉토리 생성 
        install ./MainTest $(DESTDIR) ##생성 후 이를 이 디렉토리에 복사 

test-version-recur1:
        @echo    Building other program1      ##다른 Make program 관리
        @cd test-rec; cd `find . -name "*test*"`; make   CROSS_COMPILE=$(CROSS_COMPILE)

test-version-recur2:
        @echo    Building other program2      ##다른 Make program 관리
        make -J 2 -C $(TEST_PATH)/test-*   ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE)  


##   @을 사용하면, 사용하는 command 실행되는 과정을 안보이게 할수 있다. 


3.2  Make의 recipe 에 script 적용

Shell Script의 기능을 Make 안에 적용하는 것이지만 변수 사용법 이부분은 아래의 변수사용법 참조

이를 이용하면 좀 더 복잡하고 정교한 Make를 만들 것이 가능하다.
이 뿐만 아니라, sed , awk 등 다양한 것을 적용가능하다.
기본 Script를 익혀서 이를 Makefile 내부에 적용을 해보자

  • 주의 및 확인사항 ( 반드시 확인 )
  1. 보통 line이 길어지는 '\'을 사용하여 다음줄로 한다. 이때 '\' 다음에  \n로 하고 빈공간을 없애자.
  2. Script 내부에 세미콜론(;)을 주의하자 
  3. Makefile은 탭이 중요하기때문에 다시 확인하자
  4. Script 실행되는 것을 되는것을 보이지 않게하려면 @사용하여 전체를 가리자. 
  5. Loop 문의 구분자, 즉 변수들을 구분하는 구분자는 스페이스이다. 
아래의 예제들은 Makefile 안에 반드시 탭과 함께 넣어야 해야 동작을 한다.
그리고 위에서 설명했듯이 Loop의 List 변수의 구분자는 스페이스 이다.

  • Recipe 안의 변수 사용법
  receipe 안에서 변수 사용할경우, 반드시 $$로 사용해야한다
  https://www.gnu.org/software/make/manual/html_node/Variables-in-Recipes.html


A. For Loop 예제-1   (recipe 안에서  $$사용) 


  1. $SUB_DIRS에서 하나씩 가져와서 dir 변수를 사용하여 반복되는 Loop문 구조
  2. @을 한번사용하여 전체적용  

@for dir in $(SUB_DIRS); 
do \
     $(MAKE) -C $$dir clean; \
done

B. For Loop 예제-2

아래와 같이 1 2 3의 구분자는 스페이스이다.
  1. 상위와 같지만, 1,2,3을 직접넣어 변수 i에 작동하는 Loop 구조
  2. @을 하나를 사용하여 전체 적용하여, 변수는 $${i} or $$i로 사용

@for i in 1 2 3; \
do \
      echo TEST$${i}_$$i ; \
done

C. For Loop 예제-3

  1. 상위와 기본구조가 같지만 이중루프로 동작
  2. @을 한번사용하여 전체적용

@for i in 1 2 3; \
do \
    for j in 1 2 3 4 5; \
        do \
          echo TEST$${i}_$$j ; \
       done; \
done

D. IF문 및 EXIT 예제-1  (File 및 Directory 존재 여부 확인)

  1. if 문 File 및 Diretory으로 점검하는 구조
  2. exit 1는 에러로 표시하여 추후 재귀호출시 에러점검.

@if [ -f test]; then \
    echo "You have test file \                   
else \
    echo You have no test file \
    exit 1; 
fi

@if [ ! -d $(DIR) ]; then \
    echo "You have no test directory  \                   
fi

@if [ -e $(FILE) ]; then \
    echo "You have test file \                   
fi

@if [ -d test]; then \
    echo "You have test directory \                   
else \
    echo You have no test directory \
    exit 1; 
fi


  • IF/LOOP및 기타 기본예제 
  http://linuxcommand.org/wss0090.php
  http://egaoneko.github.io/os/2015/05/24/linux-starter-guide-8.html#fnref:1

  • IF/CASE 예제
  http://atcamp.co.kr/cosmos/solar/read.php?board=class&uid=13&cafeid=23

  • Bash Script 여러예제
  http://www.thegeekstuff.com/tag/bash-tutorial/

  • Bash Loop/awk 활용 
  http://www.thegeekstuff.com/2011/07/bash-for-loop-examples/?utm_source=feedburner


4. GCC의 다양한 Option 설정 

이부분은 상위 Implicit-Variables 와 연관이 있으며 Make 내부에 GCC의 옵션 변경을 할때 아래와 같이 GCC Manual을 이용하여 설정을 변경하자

아래의 GCC 옵션들은 GCC-5.4.0 기준이며, 본인이 사용하는 GCC version에 맞추어
문서를 찾아 Index를 찾으면 될 것이다.

  • Index 주의사항 
   '-' 이 제거가 되어있기에  ABCD 순서대로만 찾으면 된다.
  https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Option-Index.html#Option-Index

  • ARM 용 별도의 option 
  https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/ARM-Options.html#ARM-Options


5. Make의 관련 다양한 예제

Make의 기본 기능은 Target과 그의 종속된 Target 을 연결하여 실행하는 것이다.
그리고, Make를 재귀적용법으로도 실행을 하여 다른 Makefile을 제어도 가능하다.

  • Simple Makefile 
  http://korea.gnu.org/manual/4check/make-3.77/ko/make_2.html#SEC6

  • 사용목적과 기본사용방법
  최근에 찾은사이트로 기본사용법이 잘나와 있어 좋다.
  https://www.joinc.co.kr/w/Site/C/Documents/minzkn_make
  http://developinghappiness.com/?p=28


  • Make의 재귀적 용법사용
  1.  일반적으로는 make -C 옵션을 주어 내부에서 재귀적으로 호출한다. 
  2.  다른방법은 cd로 직접 해당주소로 가서 make를 실행을 한다. 
  https://www.gnu.org/software/make/manual/html_node/Recursion.html#Recursion



6. GNU Make Manual 관련사항 

  • GNU Make의 전체 Manual  
      https://www.gnu.org/software/make/manual/html_node/index.html#SEC_Contents
      http://korea.gnu.org/manual/4check/make-3.77/ko/make_toc.html
      https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make.html#toc8

    GNU Make의 Manual 내용이 많다보니, 상위 Manual에서도 아래와 같이 읽어보라고 권하고 있다.

    • GNU Make의 Manual 
    1. Introduction  : 소개 
    2. Features : 기본 기능 
    3. Incompatibilities and Missing Features : 비호환성과 빠진 기능 
    4. Special Target : 내부에 암묵적으로 사용가능한 Target 
    5. Quick-Reference:  Make에 익숙하다면, 많이 도움이되는 Page 
    6. Options-Summary: Make의 재귀를 사용시 Make의 option 기능을 알수 있다. 
      https://www.gnu.org/software/make/manual/html_node/Introduction.html#Introduction
      https://www.gnu.org/software/make/manual/html_node/Features.html#Features
      https://www.gnu.org/software/make/manual/html_node/Missing.html#Missing
      https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets
      https://www.gnu.org/software/make/manual/html_node/Quick-Reference.html#Quick-Reference
      https://www.gnu.org/software/make/manual/html_node/Options-Summary.html#Options-Summary

    • GNU Make Index
      https://www.gnu.org/software/make/manual/html_node/Concept-Index.html#Concept-Index


    7. Kernel Makefile 관련내용 

    Kernel Makefile을 보면 상위부분은 복잡하지만, 밑으로 갈수록으로 모듈화가 잘되어있어
    사용하기가 편하다.
    U-Boot Makefile 역시 비슷하지만 다르게 구성이 되어있지만, 유사한 부분이 많이 있다.

    솔직히 Kernel Makefile과 U-Boot Makefile은 수정할 일이 거의 없으며 간단한 Config 규칙과 Makefile 추가하는 식을 알면된다.

    • obj-y obj-n -obj-m 설정 

      https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt

    2/01/2016

    GNU Make 의 Makefile 구성 (추후 문서 작성)

    1. GNU Make를 이용하여 Makefile 구성 

    이전에 알아두었던 내용으로, 이제 각각의 Makefle을 구성을 해보자.
    하지만, 각각의 Makefile의 구성마다 구성방법을 다르게 하겠다.

    일단, Main Source 맨 위에 존재하고, 각각의 directory 안에 source가 함수가 존재하며, 이는 이는 Main 함수에 종속이 된다고 가정하겠다.
    그리고, 이에 기반으로 Makefile을 만들어 보겠다.


    2. 기본 Makefile 만들기 

    보통 Makefile을 만든다고 하면 Build를 위해 만들것이며, 아래와 같이 두 부류로 구성이 가능할 것 같다.
    보통 이렇게 많이들 사용하는 것 같다.


    이를 이해 하기전에 Static/Shared Library 및 관련사항을 알고 가자.
    • Linux Static 와 Shared Library의 기본이해 
    아래에서 GCC를 이용하여 Static Library와 Shared Library를 생성하는 법을  간단히 익혀보자.
        http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
        http://blog.naver.com/PostView.nhn?blogId=xogml_blog&logNo=130138049704

      간단하고, 속도가 요하는 부분 Static library 하고 Shared library는 대부분 open source때문에 사용할게 될 것이다.

      • Binutils Manual (ar/ranlib/nm ... so on)
      상위 Library 와 이해하기 위해서 GCC Manual과 Binutil Manual 은 대충을 알아두자.
        https://sourceware.org/binutils/docs/binutils/index.html#Top


      2.1  Makefile (Library 기반구축)

      하부 Directory 존재하여 이를 재귀호출하여 매번 Library로 만들어 구성하고
      Main에서는 만들어진 Library를  하나로 통합하는 방식을 구축하는 방식이다.
      여기서 핵심은 Library를 만드는 법이 핵심이다.

      우선 Linux의 Library의 개념을 정확히 이해를 하고 이를 진행하도록 하자
      개발자라면, ELF(Executable and Linkable Format) 대해서도 알 것이며,
      만약 모르다면,  Library 개념도 대충 알고 넘어가자.

      • Shared Library 사용할 경우 설정 
      Shared Library를 사용하기 위해서는 링킹로더가 Shared Library 찾기 위해서 아래의 설정을 해주자.


      1. LD_LIBRARY_PATH 별도 설정 
      2. Shared Library 기존에 존재하던 Shared Library Directory에 복사

        http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html


      • Sample Makefile 
      내가 아래와 같이 Linux에서 Static/Shared Library 와 함께 사용 가능하도록 Sample Makefile을 만들어보았다.

        https://github.com/JeonghunLee/make_ex_libs
                            (Download)


      아래가 최종적으로 실행되는 프로그램이며, ./libs 참조하여 -lsub1, -lsub2 참조하고
      tst1.o와 tst2.o를 참조하여 Test Program을 완성하였다.

       // libsub1 만드는 과정 
      libsub1
      ar  rv libsub1.a sub1.o sub2.o     //v는 verbose version 기능 과 r은 static library 기능을 수행  
      r - sub1.o
      r - sub2.o
      ranlib libsub1.a                   // 만들어진 library의 index를 만들어준다. (심볼테이블)
      install libsub1.a ../libs          // 만들어진 library를 ../libs 이동 
      
      // libsub2 만드는 과정              // 상위와 동일 
      libsub2
      ar  rv libsub2.a sub1.o sub2.o
      r - sub1.o
      r - sub2.o
      ranlib libsub2.a
      install libsub2.a ../libs
      
      // 만들어진 /libs 디렉토리에 안에 아래와 같이 두개의 library와  별도의 두개의 tst1.o, tst2.o 와 묶어 
      // MainTest.o 빌드하여 Program 완성 
      
      gcc -Iinclude -o MainTest MainTest.o  tst1.o tst2.o -L. -L./libs -lsub1 -lsub2  


      2.2  Makefile ( object 기반)

      하부 Directory가 많이 존재하지만, 이 전체를 전부 object로 빌드 한 후 Main에서 통합하여 관리하는 방식이다.
      상위 방식하고 차이라면, Library를 구성하지 않는 다는 것이며, 어떻게 보면, Static Library이다.

      이곳에서 구성할때 문제라고 하면 바로 sub directory의 include의 종속사항이다.
      그러므로 Makefile에서 그런부분을 선언을 별도로 해줘야한다.

      • Sample Makefile 

        아래와 같이 동일하게 Sample Makefile을 만들어 보았다.
        https://github.com/JeonghunLee/makefile_exmple_with_objs
                            (Download)


      ti-processor-sdk-linux-am335x-evm-03.00.00.04/example-applications/arm-benchmarks-1.3/dhrystone
      ~/am335x/ti-processor-sdk-linux-am335x-evm-03.00.00.04/example-applications/omapconf-1.72


      3. 관리용 Makefile  (재귀호출)

      상위 처럼 직접 Build용으로 Makefile을 만들기도 하지만, 다른 Makefile을 호출하여,
      즉 관리용 Makefile로 구성이 가능하다.

      Make의 재귀호출을 이용하여, 여러 Opensource 관리하거나, Make 후, Install을 하여,
      각각의 파일들을 관리하는 방법에 대해 기본적으로 알아보자.
      이는 보통 하위 Makefile이 많을 경우 단계를 나누어서 생각을 하는 것이 좋다.


      • 일반적인 재귀 호출들

      아래와 같이 구성을 하면, SubMake가  빌드가 될 것은 되겠지만, 한가지씩 문제점들이 발생한다.
      바로 install 문제점 이며, Make간의 변수통신일 것이다.
      그리고 대체적으로 PATH 문제도 많이 발생할 것이다 왜냐하면, 절대 PATH를 사용하지 않고 사용하는 Make가 존재하여, 이 문제들을 해결해보자.


      BASE_DIR := $(shell pwd)        # Sub Make도 이렇게 사용한다면 문제가 발생 할 것이다. 
      
      subsystem:
              cd subdir && $(MAKE)   # directory 변경하여 make 시도 
      
      subsystem:
              cd subdir && $(MAKE)  -l ../RuleMake       # -l include 다른 Make 참조 
      
      subsystem:
              cd subdir && $(MAKE)  -sk   # -s  silent, -k keep going, s와 k 만 다음 subMake에 전달됨 주의. 
      
      subsystem:
              cd subdir && $(MAKE)  -j 3  # 동시 작업수  
      
      subsystem:
              $(MAKE) -C subdir   ARCH=arm CROSS_COMPILE=$(ARM_PREFIX)    # directory 변경하여 make 시도  
              $(MAKE)  install   
      
      subsystem:
              $(MAKE) -f Makefile.mk   # -f file을 이용하여 외부 Makefile 적용한다.
      
      subsystem:
              cd subdir && $(MAKE) -f Makefile.mk clean    # -f file을 이용하여 외부 Makefile 적용한다.
      
      

      • Make 재귀호출 Manual
        https://www.gnu.org/software/make/manual/html_node/Recursion.html



      target: 
              @echo test start 
              -rm -f *.o                
              -chown -R jhlee:jhlee ./    # root 에서 문제 발생 , 원래는 sudo make 실행  
              @echo test end 
      

      target: 
              @echo test start 
              mkdir -p $(SUBDIRS)      # directory 생성 
              @echo test end  
      

      
      
      • Recipes의 에러무시 
        관리를 하다보면, 상대방의 Makefile 파일이기때문에 Recipes 중 에러가 발생했지만,
        이 에러를 무시하고 싶을 경우가 발생한다. 특히 중간 하나만,

        그럴 경우 recipes의 앞에 '-'을 붙혀주고 실행하거나, make의 옵션 '-k'를 이용하자

        https://www.gnu.org/software/make/manual/html_node/Errors.html#Errors

        https://stackoverflow.com/questions/17834582/run-make-in-each-subdirectory



      MainMake 과  SubMake의 분리하고 사용하고 이를 재귀호출할 경우 발생되는 부분이 바로 통신 부분이다.
      Main Make에서는 골치아픈지만, 위 사실을 알고 사용해야 한다.

      또 한가지는 바로 성능부분과 타겟의 이름충돌를 고려해서 PHONY를 이용하는 것이다.
      솔직히 이름충돌보다는 성능부분이 더 고려가 되겠다.



      • SubMake와 통신방법 
          SubMake와 통신은 두가지로 나누어 볼수 있다.

      1. Makefile 내부의 변수 문제부분  (export 와 unexport 로 해결)
      2. Make가 재귀 호출이 되어서 Make의 Option이 지속적으로 전달되는 부분

        https://www.gnu.org/software/make/manual/html_node/Variables_002fRecursion.html
        https://www.gnu.org/software/make/manual/html_node/Options_002fRecursion.html#Options_002fRecursion



      다음으로 make에 줄 수 있는 옵션들이며, 이는 관리용 make를 만들경우 중요하다.
      이를 이용하여, 관리용 makefile을 만들어보자.
      아래와 같이 Make의 재귀를 이용하여 Main에서 Sub Make를 관리가 가능하다.

      • Make의 호출시 다양한 옵션 소개 
        Make를 호출 할 경우, 옵션을 주어 기능을 확장이 가능하다,
        아래에서 각 기능을 확인하자.

        https://www.gnu.org/software/make/manual/html_node/Options-Summary.html




      ~/am335x/ti-processor-sdk-linux-am335x-evm-03.00.00.04/example-applications/arm-benchmarks-1.3