构建make文件的最佳实践

时间:2018-02-14 16:27:16

标签: makefile

背景:

我是Make的新手,我开始为我最近制作的奥赛罗游戏构建一个makefile。我当前的makefile相对简单。然而,我希望进一步完善它并添加构建和存档功能。

问题1: 为什么不清洁工作?

问题2: 对于存档,我打算使用

# tar cvzf *.o Othello

归档,编译时生成的.o和可执行文件。这是一个很好的标准做法还是有更好的方法来做到这一点?

问题3: 对于构建部分,我计划使用./Othello运行可执行文件这是构建makefile的最佳实践吗?

git存储库发布在下面,谢谢您的时间

全部:奥赛罗

Othello: main.o Myothello.o space.o game.o
        clang++ main.o Myothello.o space.o game.o -o Othello

main.o: main.cc
        clang++ -c main.cc

game.o: game.cc
        clang++ -c game.cc

Myothello.o: Myothello.cc
            clang++ -c Myothello.cc

space.o: space.cc
        clang++ -c space.cc

clean:
rm -f *.o core *.core
rm MyOthello

2 个答案:

答案 0 :(得分:5)

这是一个示例makefile,在您的github项目上进行了测试。

特点:

  1. 自动生成依赖关系。
  2. 更改Makefile时自动重建。
  3. 调试/发布构建在不同的目录中。调试版本是默认版本,使用make BUILD=release版本构建。
  4. 支持gccclanggcc是默认设置,make COMPILER=clang使用clang
  5. clean target的工作方式是删除整个构建目录。
  6. run目标是构建和运行,例如make run_othello
  7. 限制:

    1. 假设所有源文件都在同一目录中。在一个更大的项目中,将有多个目录,每个目录都有多个构建目标(可执行,静态或共享库)。需要同构构建目录结构来支持此功能。这是完全可行但在下面的示例Makefile中需要更复杂的内容,因此为简洁起见省略了它。
    2. 归档时,您可能只想归档源文件和makefile。无需包含任何构建工件(如目标文件,库和可执行文件)。

      # ==== Begin prologue boilerplate.
      all : # The canonical default target.
      BUILD := debug
      build_dir := ${CURDIR}/${BUILD}
      exes := # Executables to build.
      # ==== End prologue boilerplate.
      
      # ==== Begin define executable othello.
      exes += othello
      objects.othello = main.o game.o Myothello.o space.o
      -include ${objects.othello:%.o=${build_dir}/%.d} # Include auto-generated dependencies.
      # ==== End define executable othello.
      
      # ==== Begin define another executable.
      # ... as for othello
      # ==== End define another executable.
      
      # ==== Begin rest of boilerplate.
      SHELL := /bin/bash
      COMPILER=gcc
      
      CXX.gcc := /bin/g++
      CC.gcc := /bin/gcc
      LD.gcc := /bin/g++
      AR.gcc := /bin/ar
      
      CXX.clang := /bin/clang++
      CC.clang := /bin/clang
      LD.clang := /bin/clang++
      AR.clang := /bin/ar
      
      CXX := ${CXX.${COMPILER}}
      CC := ${CC.${COMPILER}}
      LD := ${LD.${COMPILER}}
      AR := ${AR.${COMPILER}}
      
      CXXFLAGS.gcc.debug := -Og -fstack-protector-all
      CXXFLAGS.gcc.release := -O3 -march=native -DNDEBUG
      CXXFLAGS.gcc := -pthread -std=gnu++14 -march=native -W{all,extra,error} -g -fmessage-length=0 ${CXXFLAGS.gcc.${BUILD}}
      
      CXXFLAGS.clang.debug := -O0 -fstack-protector-all
      CXXFLAGS.clang.release := -O3 -march=native -DNDEBUG
      CXXFLAGS.clang := -pthread -std=gnu++14 -march=native -W{all,extra,error} -g -fmessage-length=0 ${CXXFLAGS.clang.${BUILD}}
      
      CXXFLAGS := ${CXXFLAGS.${COMPILER}}
      CFLAGS := ${CFLAGS.${COMPILER}}
      
      LDFLAGS.debug :=
      LDFLAGS.release :=
      LDFLAGS := -fuse-ld=gold -pthread -g ${LDFLAGS.${BUILD}}
      LDLIBS := -ldl
      
      COMPILE.CXX = ${CXX} -c -o $@ ${CPPFLAGS} -MD -MP ${CXXFLAGS} $(abspath $<)
      PREPROCESS.CXX = ${CXX} -E -o $@ ${CPPFLAGS} ${CXXFLAGS} $(abspath $<)
      COMPILE.C = ${CC} -c -o $@ ${CPPFLAGS} -MD -MP ${CFLAGS} $(abspath $<)
      LINK.EXE = ${LD} -o $@ $(LDFLAGS) $(filter-out Makefile,$^) $(LDLIBS)
      LINK.SO = ${LD} -shared -o $@ $(LDFLAGS) $(filter-out Makefile,$^) $(LDLIBS)
      LINK.A = ${AR} rsc $@ $(filter-out Makefile,$^)
      
      all : ${exes:%=${build_dir}/%} # Build all exectuables.
      
      .SECONDEXPANSION:
      # Build an executable.
      ${exes:%=${build_dir}/%} : ${build_dir}/% : $$(addprefix ${build_dir}/,$${objects.$$*}) Makefile | ${build_dir}
          $(strip ${LINK.EXE})
      
      # Run an executable. E.g. make run_othello
      ${exes:%=run_%} : run_% : ${build_dir}/%
          @echo "---- running $< ----"
          /usr/bin/time --verbose $<
      
      # Create the build directory on demand.
      ${build_dir} :
          mkdir $@
      
      # Compile a C++ source into .o.
      # Most importantly, generate header dependencies.
      ${build_dir}/%.o : %.cc Makefile | ${build_dir}
          $(strip ${COMPILE.CXX})
      
      # Compile a C source into .o.
      # Most importantly, generate header dependencies.
      ${build_dir}/%.o : %.c Makefile | ${build_dir}
          $(strip ${COMPILE.C})
      
      clean :
          rm -rf ${build_dir}
      
      .PHONY : clean all run_%
      
      # ==== End rest of boilerplate.
      

答案 1 :(得分:0)

对于单个文件夹项目,我构建了这个Makefile *请注意,生成的可执行文件已更改为游戏

all: build archive

build: Game

Game: main.o Myothello.o space.o game.o
    clang++ main.o Myothello.o space.o game.o -o Othello

main.o: main.cc
    clang++ -c main.cc

game.o: game.cc
    clang++ -c game.cc

Myothello.o: Myothello.cc
    clang++ -c Myothello.cc

space.o: space.cc
    clang++ -c space.cc

clean:
    rm -f *.o core *.core

archive: main.cc game.cc Myothello.cc space.cc char.h  colors.h game.h 
space.h Myothello.h makefile
    tar -cf archive.tar main.cc game.cc Myothello.cc space.cc char.h  
    colors.h game.h space.h Myothello.h makefile

这可以假设您的所有文件都在同一目录中 这是我找到我的信息的地方

http://www.tutorialspoint.com/makefile/makefile_example.htm

https://www.tecmint.com/18-tar-command-examples-in-linux/

https://www.gnu.org/software/make/manual/html_node/Simple-Makefile.html

ftp://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_toc.html