[Makefile]

general_var:= my-value

target: dep1 dep2

    <do something> $(general_var)

위의 makefile이 단독으로 사용되는 경우는, 전혀 문제가 되지 않는다. 그렇지만, makefile이 서로 서로 include되는 등의 복잡한 system에서는

경우에 따라, 위의 makefile이 parsing된 이후, general_var 의 값이 다른 값으로 바뀌게 될 수도 있다.(include된 다른 make file에서...)

이럴 경우, 'target'의 command section이 수행될 때는 'general_var'가 이미 다른 값으로 치환된 이후이기 때문에, 기대와 다른 동작을 하게 될 수 있다.

('blog의 variable expansion at command section on GNUMake 참조)

이것을 막기 위해서는 아래와 같은 형태로 make file을 구성해야 한다. 


[Makefile]

general_var:= my-value

target: private_var := $(general_var)

target: dep1 dep2

    <do something> $(private_var)

위의 makefile은, makefile이 parsing되고 target을 만들기 위한 rule이 수행되기 전에 아래와 같은 상태가 된다.


[Makefile]

general_var:= my-value

target: private_var := my-value

target: dep1 dep2

    <do something> $(private_var)


따라서, target 의 command section이 수행되기 전에, dependency section이 수행되면서 private_var값이 my-value로 set 되고

target 의 command section은 기대했던 'my-value' 값을 가지고 수행된다.

단, 아래와 같은 syntax는 "*** commands commence before first target.  Stop." error를 발생시키니 주의해야 한다.

(즉 dependency section에서 variable assignment를 수행할 경우, command section과 함께 있으면 안된다.) 


general_var:= my-value

target: private_var := my-value

    <do something> $(private_var)




[Makefile]

$(shell echo hello) # <--- (*A)

all:

    echo all

above make file gives following results.

     

Makefile:1: *** missing separator.  Stop.

error is issued.

But, we can resolve this error by changing line (*A) into below line.

dummy := $(shell echo hello)

or

$(shell echo)


What is root cause of this?

Let's see source code of 'func_shell' function in GNUMake-v4.0.


func_shell_base(...)

{

    ...

      child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp); <= stdout을 pipe로 redirecdtion

    ...

          EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i)); <= pipe를 읽음

    ...

          /* The child finished normally.  Replace all newlines in its output

             with spaces, and put that in the variable output buffer.  */

          fold_newlines (buffer, &i, trim_newlines);

          o = variable_buffer_output (o, buffer, i);    <= buffer값(pipe값 -> child의 stdout값)을 variable_buffer에 저장. 

    ...

}


That is, 'shell' function stores it's result(stdout) into variable_buffer.

variable_buffer is buffer that is used to store result of variable-expandsion.

What does this mean?

See below samples.


[Makefile]

$(shell echo hello) <= (*1)


[Makefile]

temp:=hello

$(temp) <= (*2)


Above analysis means, (*1) and (*2) is same expression in gnumake's point of view.


Actually, above rules are same on all other functions in gnumake.

But, most function gives empty string - that is, it doesn't write string value to stdout.

So, it doesn't write anything into variable_buffer. That's reason why above issues are not shown at other functions.

And, in gnumake's point of view, 'function' and 'variable' is same in concept.

So, we can say that 'function' is just special variable that can get arguments - a kind of 'predefined variable'.

Therefore, we should use same concept for 'variable' and 'function' to understand gnumake.


[[ Tested on GCC 4.x ]]


static void

test01_00(char buf[TEST01_SZ]) {

        printf("In func: %lu\n", sizeof(buf));

}


static void

test01(void) {

        char buf[TEST01_SZ];

        printf("In local: %lu\n", sizeof(buf));

        test01_00(buf);

}


int

main(int argc, const char *argv[]) {

        test01();

        return 0;

}


<< Run on 64bit linux >>

$ ./a.out

In local: 16   <== array size

In func: 8     <== pointer size


'sizeof(<array>)' works as expected in the scope where it is declared. But, array that is declared as parameter, is regarded same as 'pointer' (as you can see above).

I don't think this is defined in C specification.

So, I think it is just one of special characteristics of GCC.

Is it interesting,isn't it?


즉 array를 선언한 곳에서 sizeof(<array>)는 기대한 대로 동작하는데, argument로 넘긴 array의 경우, pointer와 동일하게 취급하는 것을 알 수 있다.

개인적인 생각으로, 이것이, C spec 사항일 것 같지는 않다.

그러니, 그냥 GCC 특성 중 하나라고 생각한다....

꽤나 재미있는 내용이라, 일단 적어 둔다. ^_^

'Language > C&C++' 카테고리의 다른 글

[C/C++] Small tip - Argument passed to main() function.  (0) 2015.10.19
[C/C++] Template with value  (0) 2015.04.28
[Macro] '##' macro operator  (0) 2015.02.11
'malloc' and 'Segmentation fault'  (0) 2014.07.25
[GCC] Initialize array...  (0) 2014.07.25

+ Recent posts