linux Makefile : 编译包含非当前目录的工程
2017-09-24 20:19
357 查看
序
前几天和同事聊起重构, 他想将工程结构调整下, 将每个工程和依赖的基础代码都分开.每个工程和基础代码都有单独的版本文件夹. 不同版本在Makefile中可以方便的包含. e.g. 下个版本要用1.0.1.1版的基础代码和逻辑代码, 当前版本要连接1.0.0.1版的基础代码和逻辑代码.
这样, 当前简单的Makefile就不适用了, 当前的Makefile只能编译当前目录和子目录下的实现.
今天将这个实验做了.
总体目标 : 如果工程中添加了非当前目录的编译内容, 也不要使修改Makefile的工作量太大. 因为对Makefile的编写还是个小白, 做到新添加了非当前目录编译内容, 能少改些Makefile就可以接受了.
为了可以在低版本linux内核上运行, 使用了-std=c++98的选项.
实验
重构后的目录结构
类似于下图, 目录结构为 => 工程或子工程(或依赖的公用实现)名称/工程版本/子工程文件夹名称/具体的文件名称最后要执行的Makefile在主工程中, e.g. 1_7/1.0.0.1/Makefile
├─1_7 │ └─1.0.0.1 │ │ main.cpp │ │ Makefile │ │ readme.txt │ │ │ └─empty_dir ├─3rd │ └─1.0.0.1 ├─base │ └─1.0.0.1 │ │ base_header.h │ │ │ ├─file │ ├─net │ ├─process │ └─string │ helper_string.cpp │ helper_string.h │ └─business └─1.0.0.1 │ business_header.h │ └─string
Makefile
# ============================================================================== # makefile # lostspeed 2017-09-24 # ============================================================================== # ------------------------------------------------------------------------------ # all code on PROG_VER's dir # e.g. base/PROG_VER/file # myprog/PROG_VER/main.cpp # myprog/PROG_VER/subdir/xx.cpp # the Makeile on myprog/PROG_VER/ PROG_VER = 1.0.0.1 LINE80 = -------------------------------------------------------------------------------- CC = g++ -std=c++98 CFLAGS = -Wall -g BIN = case_1_7 INC = -I. -I../../base/$(PROG_VER)/ -I../../business/$(PROG_VER)/ LIBS = -lstdc++ -pthread LIBPATH = /usr/local/lib # DEPEND_CODE_DIR is other code not in ./ or ./xx, e.g. base code, business code # if add a base code dir, append it to DEPEND_CODE_DIR e.g. ../xx_base/xx_type/ DEPEND_CODE_DIR = ../../base/$(PROG_VER)/ \ ../../base/$(PROG_VER)/file/ \ ../../base/$(PROG_VER)/net/ \ ../../base/$(PROG_VER)/process/ \ ../../base/$(PROG_VER)/string/ \ ../../business/$(PROG_VER)/ \ ../../business/$(PROG_VER)/log/ \ DEPEND_CODE_SRC = $(shell find $(DEPEND_CODE_DIR) -name '*.cpp') DEPEND_CODE_OBJ = $(DEPEND_CODE_SRC:.cpp=.o) # root code dir is ./'s code, e.g. main.cpp ROOT_CODE_SRC = $(shell find ./ -name '*.cpp') ROOT_CODE_OBJ = $(ROOT_CODE_SRC:.cpp=.o) # if no sub code dir, must fill a sub dir exist but empty. e.g. ./empty_dir # if have sub code dir, fill it like DEPEND_CODE_DIR # e.g. ./xx_subdir/xx_type/ SUB_CODE_DIR = ./empty_dir SUB_CODE_SRC = $(shell find $(SUB_CODE_DIR) -name '*.cpp') SUB_CODE_OBJ = $(SUB_CODE_SRC:.cpp=.o) help: clear @echo $(LINE80) @echo "ROOT_CODE_SRC = " $(ROOT_CODE_SRC) @echo "ROOT_CODE_OBJ = " $(ROOT_CODE_OBJ) @echo "DEPEND_CODE_DIR = " $(DEPEND_CODE_DIR) @echo "DEPEND_CODE_SRC = " $(DEPEND_CODE_SRC) @echo "DEPEND_CODE_OBJ = " $(DEPEND_CODE_OBJ) @echo "SUB_CODE_DIR = " $(SUB_CODE_DIR) @echo "SUB_CODE_SRC = " $(SUB_CODE_SRC) @echo "SUB_CODE_OBJ = " $(SUB_CODE_OBJ) @echo "INC = " $(INC) clean: clear @echo $(LINE80) @echo make clean rm -f $(BIN) $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ) all:$(BIN) @echo $(LINE80) @echo make all chmod 777 $(BIN) find . -name $(BIN) $(BIN) : $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ) $(CC) $(CFLAGS) -o $@ $^ .cpp.o: $(CC) -c $(CFLAGS) $^ -o $@ $(INC) -L$(LIBPATH) $(LIBS) rebuild: make clean @echo $(LINE80) make all rebuild_and_run: make rebuild @echo $(LINE80) ./$(BIN)
做实验的测试工程
这个测试代码中没有的实现, 都放在其他目录中(非主工程及其子目录, ), 在Makefile中指定路径和编译连接.// @file 1_7.cpp // @brief ... #include "base_header.h" #include "business_header.h" #include "string/helper_string.h" int main(int argc, char** argv) { int status = 0; pid_t pid = 0; char sz_buf[MAXLINE] = {'\0'}; printf(">> 1-7\n"); printf("# "); // show command tip char while (NULL != fgets(sz_buf, sizeof(sz_buf), stdin)) { if (strlen(sz_buf) > 0) { sz_buf[strlen(sz_buf) -1] = '\0'; } pid = fork(); printf("fork()'s PID = %d\n", pid); if (pid < 0) { show_err_and_quit("fork error"); } else if (0 == pid) { printf("son process code : %s\n", sz_buf); execlp(sz_buf, sz_buf, (char*)NULL); // if execlp ok, can't do code below printf("after execlp\n"); err_ret("can't execute : %s", sz_buf); exit(127); } else { // this is parent fork's son process printf("waitpid\n"); pid = waitpid(pid, &status, 0); if (pid < 0) { show_err_and_quit("waitpid error"); } // ok, son process over, can continue printf("# "); // show command tip char } } exit(0); }
工程的编译
在Makefile中弄了一个rebuild_and_run参数, 编译完, 直接可以跑起来测试.root@debian750devmin:/home/lostspeed/dev/1_7/1.0.0.1# make rebuild_and_run
-------------------------------------------------------------------------------- make clean rm -f case_1_7 ./main.o ../../base/1.0.0.1/string/helper_string.o ../../base/1.0.0.1/string/helper_string.o make[2]: 警告:检测到时钟错误。您的创建可能是不完整的。 make[2]: Leaving directory `/home/lostspeed/dev/1_7/1.0.0.1' -------------------------------------------------------------------------------- make all find: “../../business/1.0.0.1/log/”: 没有那个文件或目录 make[2]: Entering directory `/home/lostspeed/dev/1_7/1.0.0.1' make[2]: Warning: File `Makefile' has modification time 4.3e+04 s in the future g++ -std=c++98 -c -Wall -g main.cpp -o main.o -I. -I../../base/1.0.0.1/ -I../../business/1.0.0.1/ -L/usr/local/lib -lstdc++ -pthread g++ -std=c++98 -c -Wall -g ../../base/1.0.0.1/string/helper_string.cpp -o ../../base/1.0.0.1/string/helper_string.o -I. -I../../base/1.0.0.1/ -I../../business/1.0.0.1/ -L/usr/local/lib -lstdc++ -pthread g++ -std=c++98 -Wall -g -o case_1_7 main.o ../../base/1.0.0.1/string/helper_string.o -------------------------------------------------------------------------------- make all chmod 777 case_1_7 find . -name case_1_7 ./case_1_7 make[2]: 警告:检测到时钟错误。您的创建可能是不完整的。 make[2]: Leaving directory `/home/lostspeed/dev/1_7/1.0.0.1' make[1]: 警告:检测到时钟错误。您的创建可能是不完整的。 make[1]: Leaving directory `/home/lostspeed/dev/1_7/1.0.0.1' -------------------------------------------------------------------------------- ./case_1_7 >> 1-7 # ^Cmake: *** [rebuild_and_run] 中断
相关文章推荐
- 仅在当前目录编译的通用Makefile
- linux之在当前目录下删除不包含aa的文件
- Makefile方法编译Linux下多文件工程
- linux下查找当前目录下,所以包含&quot;&lt;s3c2410.h&gt;&quot;的普通文件
- Linux 工程编译调试Makefile及技巧
- Makefile编译当前目录下所有c文件到共享库
- linux下编译工程(使用命令行、Makefile、cmake编译helloworld)
- Linux查找当前目录及其子目录下所有包含指定字符串的文件
- 一个较为通用的linux工程目录架构和Makefile
- 一个简单的makefile的实现,编译当前目录下所有的.c文件
- linux下C工程层级目录的Makefile编写
- linux查找当前目录下包含某一单词的所有文件并进行替换
- Linux工程下所有C代码编译Makefile模板
- linux下查找当前目录下内容包含字符串“***”的文件
- 两个简单的makefile的实现,编译当前目录下所有的.c文件
- 【Linux学习】 写一个简单的Makefile编译源码获取当前系统时间
- linux命令行查找当前目录下所有文件是否包含特定string
- 从linux主目录中的makefile文件分析编译构成。。。
- [linux]查找当前目录下所有文件内容是否包含某字符
- 【Linux学习】 写一个简单的Makefile编译源码获取当前系统时间