makepp/make for prebuild target

2023-12-13 20:55:13

考虑一个场景,某些cpp文件是通过脚本生成的,并且生成的文件数目还很多,所以想用$(wildcard )来模糊匹配出生成的所有cpp文件,想用make/makepp来构建工程。
Linux 实验环境如下:
make版本: /home/utils/make-3.81/bin/make
makepp版本: /home/utils/makepp-2.0/bin/makepp

 main.cpp

#include <iostream>
using namespace std;

int main() {
 cout << "hello world" << endl;

}
### gen.sh

#!/bin/bash
mkdir gen
cd gen
echo "" > a.cpp
echo "" > b.cpp

不可行的方案

gen:
    gen.sh

CPPFILES = main.cpp
CPPFILES += $(wildcard /*.cpp)

main : $(CPPFILES)
    @echo CPPFILES = $(CPPFILES)
    @echo folder = $(folder)
    /home/utils/gcc-5.2.0/bin/g++ $(CPPFILES) -o main

$(phony clean):
    rm -rf gen main

$ makepp main
makepp: Loading makefile /home/<…>/File/cpp/makepp/Makeppfile
makepp: Entering directory /home/<…>/File/cpp/makepp
CPPFILES = main.cpp
folder =
/home/utils/gcc-5.2.0/bin/g++ main.cpp -o main
makepp: 1 file updated and 0 phony targets built

可以看到a.cpp和b.cpp 并没有被编译。这主要是因为求CPPFILES这个变量的值的时候,gen这个target还没有被执行(在本例中其压根不会被执行),所以$(wildcard )执行结束之后结果为空。

可行方案

make 方案

### Makefile
$(shell gen.sh)

CPPFILES = main.cpp
CPPFILES += $(wildcard gen/*.cpp)

main : $(CPPFILES)
    @echo CPPFILES = $(CPPFILES)
    /home/utils/gcc-5.2.0/bin/g++ $(CPPFILES) -o main

$(phony clean):
    rm -rf gen main

$ make main
make: Warning: File `gen/a.cpp’ has modification time 0.0044 s in the future
CPPFILES = main.cpp gen/a.cpp gen/b.cpp
/home/utils/gcc-5.2.0/bin/g++ main.cpp gen/a.cpp gen/b.cpp -o main
make: warning: Clock skew detected. Your build may be incomplete.

注意此时有warning,不确定是否有影响。

makepp 方案

### Makeppfile
gen:
    gen.sh
#prebuild gen
folder := $(shell echo $(prebuild gen))

CPPFILES = main.cpp
CPPFILES += $(wildcard gen/*.cpp)

main : $(CPPFILES)
    @echo CPPFILES = $(CPPFILES)
    @echo folder = $(folder)
    /home/utils/gcc-5.2.0/bin/g++ $(CPPFILES) -o main

$(phony clean):
    rm -rf gen main

pdx-xterm-24:/home/<…>/File/cpp/makepp> makepp main
makepp: Loading makefile /home/<…>/File/cpp/makepp/Makeppfile
makepp: Entering directory /home/<…>/File/cpp/makepp
gen.sh
makepp: Scanning /home/<…>/File/cpp/makepp/gen/a.cpp
makepp: Scanning /home/<…>/File/cpp/makepp/gen/b.cpp
CPPFILES = main.cpp gen/a.cpp gen/b.cpp
folder = gen
/home/utils/gcc-5.2.0/bin/g++ main.cpp gen/a.cpp gen/b.cpp -o main
makepp: 2 files updated and 0 phony targets built

  1. 可以直接把folder := $(shell echo $(prebuild gen)) 换为 prebuild gen, 这也是更加推荐的方式。此处的prebuild关键字的介绍参考这里
  2. 也可以在wildcard那里修改:CPPFILES += $(wildcard $(prebuild gen)/*.cpp),这是第二推荐的方式, $(prebuild )函数的用法参考这里
  3. folder := $(shell echo $(prebuild gen)), 注意此处的 :=, 这是很重要的,对于makepp,也可以使用 ;=, 参考这里对;的介绍,其 和 := 的作用相同,唯一不同的是右边的表达式只会被执行一次并记录下来,对于那些开销大的命令比较有用。后续如果还有相同的表达式,会直接使用记录值来减小开销。

如果此处改为 =, 会产生奇怪的现象,我目前还无法解释:

### Makeppfile2
gen:
    gen.sh
#prebuild gen
folder = $(shell echo $(prebuild gen))

CPPFILES = main.cpp
CPPFILES += $(wildcard gen/*.cpp)

main : $(CPPFILES)
    @echo CPPFILES = $(CPPFILES)
    @echo folder = $(folder)
    /home/utils/gcc-5.2.0/bin/g++ $(CPPFILES) -o main

$(phony clean):
    rm -rf gen main

$ makepp main
makepp: Loading makefile /home/<…>/File/cpp/makepp/Makeppfile
makepp: Entering directory /home/<…>/File/cpp/makepp
gen.sh
makepp: Scanning /home/<…>/File/cpp/makepp/gen/a.cpp’
makepp: Scanning `/home/<…>/File/cpp/makepp/gen/b.cpp’
CPPFILES = main.cpp
folder = gen
/home/utils/gcc-5.2.0/bin/g++ main.cpp gen/a.cpp gen/b.cpp -o main
makepp: 2 files updated and 0 phony targets built

makepp 关键字介绍参考这里
makepp介绍参考这里

similar interesting issue:https://stackoverflow.com/questions/53603406/makefile-with-generated-c-source-files

文章来源:https://blog.csdn.net/baidu_35679960/article/details/134979740
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。