背景
在Makefile recipe中执行另外一个目录下的Makefile,图简单使用了cd命令,但是测试发现cd命令未生效,示例代码如下:
test:
cd workspace
make
cd -
test:
make -C workspace
以上代码首先会切换到workspace目录,再执行此目录下的Makefile,且会有以下打印,workspace下的Makefile执行完后,会切换回原来的目录和Makefile。
make[1]: Enter directory 'xxxxx'
.....
make[1]: Leaving directory 'xxxxx'
cd 命令不生效原因
从网上可找到答案:cd只有在当前行有效,所以代码需要更改为:
test:
cd workspace && make && cd -
使用strace工具分析下面Makefile的执行调用
命令:
strace make
Makefile:
all:
cd test
mkdir test
strace 结果:
...
read(3, "\n\nall:\n\tcd test\n\tmkdir test\n", 4096) = 28
read(3, "", 4096) = 0
close(3) = 0
stat("RCS", 0x7ffd29716440) = -1 ENOENT (No such file or directory)
stat("SCCS", 0x7ffd29716440) = -1 ENOENT (No such file or directory)
stat("Makefile", {st_mode=S_IFREG|0664, st_size=28, ...}) = 0
stat("all", 0x7ffd29714240) = -1 ENOENT (No such file or directory)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 37), ...}) = 0
write(1, "cd test\n", 8cd test
) = 8
pipe([3, 4]) = 0
close(4) = 0
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT TERM XCPU XFSZ], NULL, 8) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1c96ff5a10) = 5471
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 5471
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=5471, si_uid=994, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn({mask=[]}) = 5471
write(1, "mkdir test\n", 11mkdir test
) = 11
rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT TERM XCPU XFSZ], NULL, 8) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1c96ff5a10) = 5472
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
wait4(-1, mkdir: cannot create directory ‘test’: File exists
[{WIFEXITED(s) && WEXITSTATUS(s) == 1}], 0, NULL) = 5472
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=5472, si_uid=994, si_status=1, si_utime=0, si_stime=0} ---
...
执行make命令时,make程序读取Makefile文件。 将读取到的数据按字符串形式通过TAB符号拆分处理,每次执行一行命令 执行每一行命令都是通过clone一个子进程并等待其处理完,该操作非常类似于通过system函数执行命令,因此每一次执行只会影响当前进程,不会影响父进程。
总结