【持续更新】总结:C++开发时积累的一些零碎的东西

 

Makefile template update:

1.调整了顺序,把经常编辑的部分集中在了Makefile的下半部分

2.进行了一些重构实现更多的代码复用,见红色高亮部分,LIBPATH_ALL和LIBFILE_ALL的引入简化了LINK命令,思想与HEADER_PATH一样,你需要多少就往里写多少,你不需要,就留空,从而避免了直接去修改LINK或者COMPILE命令。AR_OBJ和LINK_OBJ也是为了简化LIB或者LINK命令

 

NMAKE

# configurations

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, !UNDEF LIB_GEN as you can see below

# By default, DEBUG is on. To turn it off, use 'nmake DEBUG=0 ', eg. 'nmake DEBUG=0' to build the product
# and 'nmake DEBUG=0 clean' to clean the product.
DEBUG = 1

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = cl
# linker
LINK = link

# options
EHSC = /EHsc
COMPILATION_ONLY = /c
C_OUT = /Fo:
L_OUT = /OUT:

# compiler & linker debug options:
!IF $(DEBUG)==1
C_DEBUG = /Zi
L_DEBUG = /DEBUG
!ELSE
# No debug flags
!ENDIF

# libraries
LIBPATH_REPLACEALL = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\lib
LIBFILE_REPLACEALL = ReplaceAll.lib
HEADER_REPLACEALL = /I E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\include

HEADER_REQUIRE = /I E:\cppwksp\thinkingincppvol2\demo\570-require\include

HEADER_BOOST = /I F:\ZJ\tools\cpp_libs\boost_1_57_0

HEADER_URAND = /I E:\cppwksp\thinkingincppvol2\demo\176-Urand\include

HEADER_APPLYSEQUENCE = /I E:\cppwksp\thinkingincppvol2\demo\195-ApplySequence\include

HEADER_PURGE = /I E:\cppwksp\thinkingincppvol2\demo\392-purge\include

HEADER_GENERATORS = /I E:\cppwksp\thinkingincppvol2\demo\259-FunctionObjects\include
LIBPATH_GENERATORS = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\259-FunctionObjects\lib
LIBFILE_GENERATORS = Generators.lib

HEADER_NUMSTRINGGEN = /I E:\cppwksp\thinkingincppvol2\demo\268-NumStringGen\include
LIBPATH_NUMSTRINGGEN = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\268-NumStringGen\lib
LIBFILE_NUMSTRINGGEN = NumStringGen.lib

HEADER_THIS = /I $(PATH_INC)

# headers & library files

HEADER_PATH = $(HEADER_THIS) $(HEADER_NUMSTRINGGEN)

LIBPATH_ALL = $(LIBPATH_NUMSTRINGGEN)
LIBFILE_ALL = $(LIBFILE_NUMSTRINGGEN)

# Generate different targets - debug or product.
!IF $(DEBUG)==1

debug: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)\test.exe

# Flags to control cleanup
# PATH_BIN and BIN_GEN must appear in pairs, the same applies to PATH_LIB and LIB_GEN
BIN_GEN = TRUE

!ELSE

product: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)\test.exe

BIN_GEN = TRUE

# LIB_GEN = TRUE

!ENDIF 

# targets

# Object files for archiver (LIB.exe or ar)
AR_OBJ =
# Object files for linker
LINK_OBJ = $(PATH_OBJ)\ComposeFinal.obj

$(PATH_BIN)\test.exe: $(LINK_OBJ)
	$(LINK) $(L_DEBUG) $(LIBPATH_ALL) $(L_OUT)$(PATH_BIN)\test.exe $(LINK_OBJ) $(LIBFILE_ALL)

$(PATH_OBJ)\ComposeFinal.obj: $(PATH_SRC)\ComposeFinal.cpp
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)\ComposeFinal.cpp $(C_OUT)$(PATH_OBJ)\ComposeFinal.obj

# folders

$(PATH_BIN):
	mkdir $(PATH_BIN)
	
$(PATH_LIB):
	mkdir $(PATH_LIB)

$(PATH_OBJ):
	mkdir $(PATH_OBJ)
	
# clean

.PHONY: clean
clean:
!IFDEF LIB_GEN
	-rmdir /s /q $(PATH_LIB)
!ENDIF
!IFDEF BIN_GEN
	-rmdir /s /q $(PATH_BIN)
!ENDIF
    -rmdir /s /q $(PATH_OBJ)
!IF $(DEBUG)==1
	-del *.pdb
!ENDIF

 

GNU-MAKE

# configurations

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, comment out DEBUG so LIB_GEN will not be defined.

# By default, DEBUG is on. To turn it off, use 'make DEBUG=0 ', eg. 'make DEBUG=0' to build the product
# and 'make DEBUG=0 clean' to clean the product.
DEBUG = 1

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = g++
# linker
LINK = g++

# options
COMPILATION_ONLY = -c
C_OUT = -o
L_OUT = -o

# compiler & linker debug options:
ifeq ($(DEBUG),1)
C_DEBUG = -g
L_DEBUG = -ggdb
else
# No debug flags
endif

# Some of ZThread's code are old-fashioned and may not be accepted by modern compilers
FPERMISSIVE = -fpermissive

# libraries
LIBPATH_ZTHREAD = -L/home/lqr/Documents/ZThread-2.3.2/lib
LIBFILE_ZTHREAD = -lZThread -lpthread

LIBPATH_SYNC_OUTPUT = -L/home/lqr/Documents/ZJ/531-SynchronizedOutput-linux/lib
LIBFILE_SYNC_OUTPUT = -lSynchronizedOutput

HEADER_SYNC_OUTPUT = -I/home/lqr/Documents/ZJ/531-SynchronizedOutput-linux/include

HEADER_ZTHREAD = -I/home/lqr/Documents/ZThread-2.3.2/include

HEADER_APUE = -I/home/lqr/Documents/ZJ/APUE/include
LIBPATH_APUE = -L/home/lqr/Documents/ZJ/APUE/lib
LIBFILE_APUE = -lapue

HEADER_UTIL = -I/home/lqr/Documents/ZJ/APUE/demo/Figure2.16-util-path_alloc/include
LIBPATH_UTIL = -L/home/lqr/Documents/ZJ/APUE/demo/Figure2.16-util-path_alloc/lib
LIBFILE_UTIL = -lutil

HEADER_THIS = -I$(PATH_INC)

# headers

HEADER_PATH = $(HEADER_THIS)

LIBPATH_ALL = $(LIBPATH_APUE)
LIBFILE_ALL = $(LIBFILE_APUE)

# Generate different targets - debug or product.
ifeq ($(DEBUG),1)

# you may remove $(PATH_BIN) and $(PATH_OBJ) if they are not needed
debug: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)/test_exe

# Flags to control cleanup
# If PATH_BIN is created, then you must define BIN_GEN, otherwise
# the cleanup logic will not delete PATH_BIN, the same applies
# to PATH_LIB
# In other words, PATH_BIN and BIN_GEN must appear in pair,
# the same applies to PATH_LIB and LIB_GEN

BIN_GEN = TRUE

else

# you may add $(PATH_LIB) if it's necessary
product: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)/test_exe

BIN_GEN = TRUE

endif

# targets

# Object files for archiver (LIB.exe or ar)
AR_OBJ =
# Object files for linker
LINK_OBJ = $(PATH_OBJ)/demo.o

$(PATH_BIN)/test_exe: $(LINK_OBJ)
	$(LINK) $(L_DEBUG) $(LIBPATH_ALL) $(L_OUT) $(PATH_BIN)/test_exe $(LINK_OBJ) $(LIBFILE_ALL)

$(PATH_OBJ)/demo.o: $(PATH_SRC)/demo.cpp
	$(CC) $(FPERMISSIVE) $(C_DEBUG) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)/demo.cpp $(C_OUT) $(PATH_OBJ)/demo.o

# folders

$(PATH_BIN):
	mkdir $(PATH_BIN)
	
$(PATH_LIB):
	mkdir $(PATH_LIB)

$(PATH_OBJ):
	mkdir $(PATH_OBJ)
	
# clean

.PHONY: clean
clean:
ifeq ($(LIB_GEN),TRUE)
	-rm -r -f $(PATH_LIB)
endif
ifeq ($(BIN_GEN),TRUE)
	-rm -r -f $(PATH_BIN)
endif
	-rm -r -f $(PATH_OBJ)

 

--------------------------------------------------------------------------

Makefile template update:

NMAKE

 

# configurations

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, !UNDEF LIB_GEN as you can see below

# By default, DEBUG is on. To turn it off, use 'nmake DEBUG=0 <target-name>', eg. 'nmake DEBUG=0' to build the product
# and 'nmake DEBUG=0 clean' to clean the product.
DEBUG = 1

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = cl
# linker
LINK = link

# options
EHSC = /EHsc
COMPILATION_ONLY = /c
C_OUT = /Fo:
L_OUT = /OUT:

# libraries
LIBPATH_REPLACEALL = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\lib
LIBFILE_REPLACEALL = ReplaceAll.lib
HEADER_REPLACEALL = /I E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\include

HEADER_REQUIRE = /I E:\cppwksp\thinkingincppvol2\demo\570-require\include

HEADER_BOOST = /I F:\ZJ\tools\cpp_libs\boost_1_57_0

HEADER_URAND = /I E:\cppwksp\thinkingincppvol2\demo\176-Urand\include

HEADER_APPLYSEQUENCE = /I E:\cppwksp\thinkingincppvol2\demo\195-ApplySequence\include

HEADER_PURGE = /I E:\cppwksp\thinkingincppvol2\demo\392-purge\include

HEADER_GENERATORS = /I E:\cppwksp\thinkingincppvol2\demo\259-FunctionObjects\include
LIBPATH_GENERATORS = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\259-FunctionObjects\lib
LIBFILE_GENERATORS = Generators.lib

HEADER_THIS = /I $(PATH_INC)

# headers

HEADER_PATH = $(HEADER_THIS) $(HEADER_PURGE)


# compiler & linker debug options:
!IF $(DEBUG)==1
C_DEBUG = /Zi
L_DEBUG = /DEBUG
!ELSE
# No debug flags
!ENDIF

# Generate different targets - debug or product.
!IF $(DEBUG)==1

debug: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)\test.exe

# Flags to control cleanup
# PATH_BIN and BIN_GEN must appear in pairs, the same applies to PATH_LIB and LIB_GEN
BIN_GEN = TRUE

LIB_GEN = TRUE
!UNDEF LIB_GEN

!ELSE

product: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)\test.exe

BIN_GEN = TRUE

LIB_GEN = TRUE
!UNDEF LIB_GEN

!ENDIF 

# targets

$(PATH_BIN)\test.exe: $(PATH_OBJ)\MemFun2.obj
	$(LINK) $(L_DEBUG) $(L_OUT)$(PATH_BIN)\test.exe $(PATH_OBJ)\MemFun2.obj

$(PATH_OBJ)\MemFun2.obj: $(PATH_SRC)\MemFun2.cpp
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)\MemFun2.cpp $(C_OUT)$(PATH_OBJ)\MemFun2.obj

# folders

$(PATH_BIN):
	mkdir $(PATH_BIN)
	
$(PATH_LIB):
	mkdir $(PATH_LIB)

$(PATH_OBJ):
	mkdir $(PATH_OBJ)
	
# clean

.PHONY: clean
clean:
!IFDEF LIB_GEN
	-rmdir /s /q $(PATH_LIB)
!ENDIF
!IFDEF BIN_GEN
	-rmdir /s /q $(PATH_BIN)
!ENDIF
    -rmdir /s /q $(PATH_OBJ)
!IF $(DEBUG)==1
	-del *.pdb
!ENDIF

 

 

 

GNU-MAKE

测试发现GNU-MAKE貌似不支持ifdef和ifndef(参考:http://www.gnu.org/software/make/manual/html_node/Conditionals.html#Conditionals),如果想表达nmake的ifdef/ifndef就用如下代码

ifeq ($(SOME_MACRO),)
      # if SOME_MACRO isn't defined
endif

ifneq($(SOME_MACRO),)
      # if SOME_MACRO is defined
endif

例如

# configurations

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, comment out DEBUG so LIB_GEN will not be defined.

# By default, DEBUG is on. To turn it off, use 'make DEBUG=0 <target-name>', eg. 'make DEBUG=0' to build the product
# and 'make DEBUG=0 clean' to clean the product.
DEBUG = 1

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = g++
# linker
LINK = g++

# options
COMPILATION_ONLY = -c
C_OUT = -o
L_OUT = -o

# Some of ZThread's code are old-fashioned and may not be accepted by modern compilers
FPERMISSIVE = -fpermissive

# libraries
LIBPATH_ZTHREAD = -L/home/lqr/Documents/ZThread-2.3.2/lib
LIBFILE_ZTHREAD = -lZThread -lpthread

LIBPATH_SYNC_OUTPUT = -L/home/lqr/Documents/ZJ/531-SynchronizedOutput-linux/lib
LIBFILE_SYNC_OUTPUT = -lSynchronizedOutput

HEADER_SYNC_OUTPUT = -I/home/lqr/Documents/ZJ/531-SynchronizedOutput-linux/include

HEADER_ZTHREAD = -I/home/lqr/Documents/ZThread-2.3.2/include

HEADER_APUE = -I/home/lqr/Documents/ZJ/APUE/include
LIBPATH_APUE = -L/home/lqr/Documents/ZJ/APUE/lib
LIBFILE_APUE = -lapue

HEADER_THIS = -I$(PATH_INC)

# headers

HEADER_PATH = $(HEADER_THIS) $(HEADER_APUE)

# compiler & linker debug options:
ifeq ($(DEBUG),1)
C_DEBUG = -g
L_DEBUG = -ggdb
else
# No debug flags
endif

# Generate different targets - debug or product.
ifeq ($(DEBUG),1)

# you may remove $(PATH_BIN) and $(PATH_OBJ) if they are not needed
debug: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)/test_exe

# Flags to control cleanup
# If PATH_BIN is created, then you must define BIN_GEN, otherwise
# the cleanup logic will not delete PATH_BIN, the same applies
# to PATH_LIB
# In other words, PATH_BIN and BIN_GEN must appear in pair,
# the same applies to PATH_LIB and LIB_GEN

BIN_GEN = TRUE

# LIB_GEN = TRUE

else

# you may add $(PATH_LIB) if it's necessary
product: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)/test_exe

BIN_GEN = TRUE

endif

# targets

$(PATH_BIN)/test_exe: $(PATH_OBJ)/demo.o
	$(LINK) $(L_DEBUG) $(LIBPATH_APUE) $(L_OUT) $(PATH_BIN)/test_exe $(PATH_OBJ)/demo.o $(LIBFILE_APUE)

$(PATH_OBJ)/demo.o: $(PATH_SRC)/demo.cpp
	$(CC) $(FPERMISSIVE) $(C_DEBUG) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)/demo.cpp $(C_OUT) $(PATH_OBJ)/demo.o

# folders

$(PATH_BIN):
	mkdir $(PATH_BIN)
	
$(PATH_LIB):
	mkdir $(PATH_LIB)

$(PATH_OBJ):
	mkdir $(PATH_OBJ)
	
# clean

.PHONY: clean
clean:
ifeq ($(LIB_GEN),TRUE)
	-rm -r -f $(PATH_LIB)
endif
ifeq ($(BIN_GEN),TRUE)
	-rm -r -f $(PATH_BIN)
endif
	-rm -r -f $(PATH_OBJ)
ifeq ($(DEBUG),1)
	# -del *.pdb

 

 

 

--------------------------------------------------------------------------

Makefile template update(GNU make version, you can also use ideas from this update on nmake makefiles):

1. Whether to create folder PATH_OBJ PATH_BIN PATH_LIB are determined by DEBUG, if DEBUG are not defined (note that unlike nmake, GNU make does not support undef, so you have to manually comment out DEBUG) you probably don't want to create PATH_LIB, so there's an ifdef block to check whether DEBUG is defined.

2. Unlike the previous version, the creation of PATH_OBJ, PATH_BIN, PATH_LIB are in the ifdef-DEBUG block rather than in the executable target so they're controled by DEBUG

Generally speaking, the structure of this version is a bit cleaner and better organized than the previous version.

Download DEMO.

# configurations

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, comment out DEBUG so LIB_GEN will not be defined.

DEBUG = TRUE

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = g++
# linker
LINK = g++

# options
COMPILATION_ONLY = -c
C_OUT = -o
L_OUT = -o

# Some of ZThread's code are old-fashioned and may not be accepted by modern compilers
FPERMISSIVE = -fpermissive

# libraries
LIBPATH_ZTHREAD = -L/home/lqr/Documents/ZThread-2.3.2/lib
LIBFILE_ZTHREAD = -lZThread -lpthread

LIBPATH_SYNC_OUTPUT = -L/home/lqr/Documents/ZJ/531-SynchronizedOutput-linux/lib
LIBFILE_SYNC_OUTPUT = -lSynchronizedOutput

HEADER_SYNC_OUTPUT = -I/home/lqr/Documents/ZJ/531-SynchronizedOutput-linux/include

HEADER_ZTHREAD = -I/home/lqr/Documents/ZThread-2.3.2/include

HEADER_THIS = -I$(PATH_INC)

# headers

HEADER_PATH = $(HEADER_THIS) $(HEADER_ZTHREAD) $(HEADER_SYNC_OUTPUT)

# compiler & linker debug options:
ifdef DEBUG
C_DEBUG = -g
L_DEBUG = -ggdb
else
# No debug flags
endif

# Generate different targets - debug or product.
ifdef DEBUG

# you may remove $(PATH_BIN) and $(PATH_OBJ) if they are not needed
debug: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)/test.exe

# Flags to control cleanup
# If PATH_BIN is created, then you must define BIN_GEN, otherwise
# the cleanup logic will not delete PATH_BIN, the same applies
# to PATH_LIB
# In other words, PATH_BIN and BIN_GEN must appear in pair,
# the same applies to PATH_LIB and LIB_GEN

BIN_GEN = TRUE

# LIB_GEN = TRUE

else

# you may add $(PATH_LIB) if it's necessary
product: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)/test.exe

BIN_GEN = TRUE endif # targets $(PATH_BIN)/test.exe: $(PATH_OBJ)/main.o $(PATH_OBJ)/Chopstick.o $(PATH_OBJ)/Philosopher.o $(LINK) $(L_DEBUG) $(LIBPATH_ZTHREAD) $(LIBPATH_SYNC_OUTPUT) $(L_OUT) $(PATH_BIN)/test.exe $(PATH_OBJ)/main.o $(PATH_OBJ)/Chopstick.o $(PATH_OBJ)/Philosopher.o $(LIBFILE_ZTHREAD) $(LIBFILE_SYNC_OUTPUT) $(PATH_OBJ)/main.o: $(PATH_SRC)/main.cpp $(PATH_INC)/Philosopher.h $(PATH_INC)/Chopstick.h $(CC) $(FPERMISSIVE) $(C_DEBUG) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)/main.cpp $(C_OUT) $(PATH_OBJ)/main.o $(PATH_OBJ)/Philosopher.o: $(PATH_SRC)/Philosopher.cpp $(PATH_INC)/Philosopher.h $(PATH_INC)/Chopstick.h $(CC) $(FPERMISSIVE) $(C_DEBUG) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)/Philosopher.cpp $(C_OUT) $(PATH_OBJ)/Philosopher.o $(PATH_OBJ)/Chopstick.o: $(PATH_SRC)/Chopstick.cpp $(PATH_INC)/Chopstick.h $(CC) $(FPERMISSIVE) $(C_DEBUG) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)/Chopstick.cpp $(C_OUT) $(PATH_OBJ)/Chopstick.o # folders $(PATH_BIN): mkdir $(PATH_BIN) $(PATH_LIB): mkdir $(PATH_LIB) $(PATH_OBJ): mkdir $(PATH_OBJ) # clean .PHONY: clean clean: ifdef LIB_GEN -rm -r -f $(PATH_LIB) endif ifdef BIN_GEN -rm -r -f $(PATH_BIN) endif -rm -r -f $(PATH_OBJ) ifdef DEBUG # -del *.pdb endif

 The improved version for nmake is like the following. Download demo.

# configurations

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, !UNDEF LIB_GEN as you can see below

DEBUG = TRUE
#!UNDEF DEBUG

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = cl
# linker
LINK = link

# options
EHSC = /EHsc
COMPILATION_ONLY = /c
C_OUT = /Fo:
L_OUT = /OUT:

# libraries
LIBPATH_REPLACEALL = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\lib
LIBFILE_REPLACEALL = ReplaceAll.lib
HEADER_REPLACEALL = /I E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\include

HEADER_REQUIRE = /I E:\cppwksp\thinkingincppvol2\demo\570-require\include

HEADER_BOOST = /I F:\ZJ\tools\cpp_libs\boost_1_57_0

HEADER_URAND = /I E:\cppwksp\thinkingincppvol2\demo\176-Urand\include

HEADER_APPLYSEQUENCE = /I E:\cppwksp\thinkingincppvol2\demo\195-ApplySequence\include

HEADER_PURGE = /I E:\cppwksp\thinkingincppvol2\demo\392-purge\include

HEADER_THIS = /I $(PATH_INC)

# headers

HEADER_PATH = $(HEADER_THIS)


# compiler & linker debug options:
!IFDEF DEBUG
C_DEBUG = /Zi
L_DEBUG = /DEBUG
!ELSE
# No debug flags
!ENDIF

# Generate different targets - debug or product.
!IFDEF DEBUG

debug: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)\test.exe

# Flags to control cleanup
# PATH_BIN and BIN_GEN must appear in pairs, the same applies to PATH_LIB and LIB_GEN
BIN_GEN = TRUE

LIB_GEN = TRUE
!UNDEF LIB_GEN

!ELSE

product: $(PATH_BIN) $(PATH_OBJ) $(PATH_BIN)\test.exe

BIN_GEN = TRUE

LIB_GEN = TRUE
!UNDEF LIB_GEN

!ENDIF 

# targets

$(PATH_BIN)\test.exe: $(PATH_OBJ)\ReplaceStrings.obj
	$(LINK) $(L_DEBUG) $(L_OUT)$(PATH_BIN)\test.exe $(PATH_OBJ)\ReplaceStrings.obj

$(PATH_OBJ)\ReplaceStrings.obj: $(PATH_SRC)\ReplaceStrings.cpp
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)\ReplaceStrings.cpp $(C_OUT)$(PATH_OBJ)\ReplaceStrings.obj

# folders

$(PATH_BIN):
	mkdir $(PATH_BIN)
	
$(PATH_LIB):
	mkdir $(PATH_LIB)

$(PATH_OBJ):
	mkdir $(PATH_OBJ)
	
# clean

.PHONY: clean
clean:
!IFDEF LIB_GEN
	-rmdir /s /q $(PATH_LIB)
!ENDIF
!IFDEF BIN_GEN
	-rmdir /s /q $(PATH_BIN)
!ENDIF
    -rmdir /s /q $(PATH_OBJ)
!IFDEF DEBUG
	-del *.pdb
!ENDIF

 

-------------------------------------------------------------

Makefile模板更新:

主要是libraries和headers的更新(还是以之前的那个版本为例子):

每个library一般都有自己的header,所以,一个library设置三个:LIBFILE_XXX, LIBPATH_XXX, HEADER_XXX

然后所有的HEADER_XXX被HEADERPATH所引用,修改后如下

1、headers在libraries下方,因为headers要引用libraries中的HEADER_XXX

2、每个library包含(但不一定全包含,视情况而定)LIBFILE_XXX和LIBPATH_XXX以及HEADER_XXX

3、你可以把常用的library都定义好,然后只需要修改headers和link指令即可,就可以灵活使用模板了

4、除了configurations那一段,其他地方对路径的使用都使用MACRO_NAME,另外PATH_INC前面不要加/I,因为在target中可能用到PATH_INC引起指令错误,所以,在libraries那一段的HEADER_THIS就是指的当前project中处于“开发”阶段的headers,其实就是/I $(PATH_INC)

# configurations

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = cl
# linker
LINK = link

# libraries
LIBPATH_REPLACEALL = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\lib
LIBFILE_REPLACEALL = ReplaceAll.lib
HEADER_REPLACEALL = /I E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\include

HEADER_THIS = /I $(PATH_INC)
# headers
HEADER_PATH = $(PATH_INC) $(HEADER_REPLACEALL)

# options
EHSC = /EHsc
COMPILATION_ONLY = /c
C_OUT = /Fo:
L_OUT = /OUT:

# Flags to control cleanup
# If you need to generate executable files, make sure the following macro is defined, otherwise just comment it out.
BIN_GEN = TRUE
# If you need to generate library files, make sure the following macro is defined, otherwise just comment it out.
LIB_GEN = TRUE

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, !UNDEF LIB_GEN as you can see below

DEBUG = TRUE
!UNDEF DEBUG

# compiler & linker debug options:
!IFDEF DEBUG
C_DEBUG = /Zi
L_DEBUG = /DEBUG
!ENDIF

# If the C_DEBUG and L_DEBUG flags are empty, generate the lib file. Otherwise lib file will not be generated.
!IFDEF DEBUG

debug: $(PATH_BIN)\test.exe

!UNDEF LIB_GEN

!ELSE

product: $(PATH_BIN)\test.exe $(PATH_LIB)\FileClass.lib

!ENDIF 

# targets

$(PATH_BIN)\test.exe: $(PATH_BIN) $(PATH_OBJ) $(PATH_OBJ)\main.obj $(PATH_OBJ)\FileClass.obj
	$(LINK) $(L_DEBUG) $(L_OUT)$(PATH_BIN)\test.exe $(PATH_OBJ)\main.obj $(PATH_OBJ)\FileClass.obj

$(PATH_LIB)\FileClass.lib: $(PATH_LIB) $(PATH_OBJ)\FileClass.obj
	LIB $(L_OUT)$(PATH_LIB)\FileClass.lib $(PATH_OBJ)\FileClass.obj
	
$(PATH_BIN)\main.obj: $(PATH_SRC)\main.cpp $(PATH_INC)\FileClass.h
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)\main.cpp $(C_OUT)$(PATH_OBJ)\main.obj

$(PATH_BIN)\FileClass.obj: $(PATH_SRC)\FileClass.cpp $(PATH_INC)\FileClass.h
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)\FileClass.cpp $(C_OUT)$(PATH_OBJ)\FileClass.obj

# folders

$(PATH_BIN):
	mkdir $(PATH_BIN)
	
$(PATH_LIB):
	mkdir $(PATH_LIB)

$(PATH_OBJ):
	mkdir $(PATH_OBJ)
	
# clean

.PHONY: clean
clean:
!IFDEF LIB_GEN
	-rmdir /s /q $(PATH_LIB)
!ENDIF
!IFDEF BIN_GEN
	-rmdir /s /q $(PATH_BIN)
!ENDIF
    -rmdir /s /q $(PATH_OBJ)
!IFDEF DEBUG
	-del *.pdb
!ENDIF

 

-------------------------------------------------------------------

最新使用的Makefile

下载demo

更新:

1、主要是使用了IF ELSE这些指令,在DEBUG的情况下不生成LIB文件夹以及LIB文件,在CLEANUP的时候也不删除LIB文件夹。如果在!UNDEF DEBUG的情况下,就要生成LIB文件夹以及LIB文件。

2、对src, obj, bin, lib这些目录都用MACRO DEFINITION来代替,方便统一修改。另外,建议target-name还是使用plain-text而不是MACRO避免混淆和保证清晰,你可以在这个Makefile中看出来我是这么做的

 

使用这个Makefile模板的话,debug的时候就保留DEBUG,如果不debug就!UNDEF DEBUG,从而实现2种不同的BUILD(当然也可以扩展出更多的情况),根据具体情况修改使用即可

随笔里的Makefile内容与demo文件夹中的Makefile内容稍微有点不同(修改了一点排版的顺序),以随笔里的为准

# configurations

# src, obj, bin and lib folders paths
PATH_SRC = src
PATH_OBJ = obj
PATH_BIN = bin
PATH_LIB = lib

# headers in this project

PATH_INC = include

# compiler
CC = cl
# linker
LINK = link
# headers
HEADER_PATH = /I $(PATH_INC)
# libraries
LIBPATH_REPLACEALL = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\96-ReplaceAll\lib
LIBFILE_REPLACEALL = ReplaceAll.lib
# options
EHSC = /EHsc
COMPILATION_ONLY = /c
C_OUT = /Fo:
L_OUT = /OUT:

# Flags to control cleanup
# If you need to generate executable files, make sure the following macro is defined, otherwise just comment it out.
BIN_GEN = TRUE
# If you need to generate library files, make sure the following macro is defined, otherwise just comment it out.
LIB_GEN = TRUE

# Flag to choose targets to build, to disable debug, just comment out the following line or !UNDEF DEBUG
# Normally when debugging, you don't want to generate lib files, to do that, !UNDEF LIB_GEN as you can see below

DEBUG = TRUE
!UNDEF DEBUG

# compiler & linker debug options:
!IFDEF DEBUG
C_DEBUG = /Zi
L_DEBUG = /DEBUG
!ENDIF

# If the C_DEBUG and L_DEBUG flags are empty, generate the lib file. Otherwise lib file will not be generated.
!IFDEF DEBUG

debug: bin\test.exe

!UNDEF LIB_GEN

!ELSE

product: bin\test.exe lib\FileClass.lib

!ENDIF 

# targets

bin\test.exe: $(PATH_BIN) $(PATH_OBJ) $(PATH_OBJ)\main.obj $(PATH_OBJ)\FileClass.obj
	$(LINK) $(L_DEBUG) $(L_OUT)$(PATH_BIN)\test.exe $(PATH_OBJ)\main.obj $(PATH_OBJ)\FileClass.obj

lib\FileClass.lib: $(PATH_LIB) $(PATH_OBJ)\FileClass.obj
	LIB $(L_OUT)$(PATH_LIB)\FileClass.lib $(PATH_OBJ)\FileClass.obj
	
obj\main.obj: $(PATH_SRC)\main.cpp $(PATH_INC)\FileClass.h
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)\main.cpp $(C_OUT)$(PATH_OBJ)\main.obj

obj\FileClass.obj: $(PATH_SRC)\FileClass.cpp $(PATH_INC)\FileClass.h
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) $(PATH_SRC)\FileClass.cpp $(C_OUT)$(PATH_OBJ)\FileClass.obj

# folders

bin:
	mkdir $(PATH_BIN)
	
lib:
	mkdir $(PATH_LIB)

obj:
	mkdir $(PATH_OBJ)
	
# clean

.PHONY: clean
clean:
!IFDEF LIB_GEN
	-rmdir /s /q $(PATH_LIB)
!ENDIF
!IFDEF BIN_GEN
	-rmdir /s /q $(PATH_BIN)
!ENDIF
    -rmdir /s /q $(PATH_OBJ)
!IFDEF DEBUG
	-del *.pdb
!ENDIF

 

------------------------------------------------------------------

0、学习的时候用Editor、Make、Compiler、Linker以及Debugger还有各种工具,了解开发细节。实战的时候用IDE加快开发速度。

  除非你的项目简单到了只需要命令:compiler a.cpp就能生成a.exe。否则,请使用良好的文件组织结构:

    your_project_folder\

      src\

        module_a\

          a.cpp

          ax.cpp

          axx.cpp

        module_b\

          b.cpp

          bx.cpp

          bxx.cpp

      bin\

      lib\

        library_a\

          xxx.lib

          yyy.lib

          zzz.lib

        library_b\

          hhh.lib

          jjj.lib

          kkk.lib

      include\

        library_a\

          iii.h

          uuu.h

        library_b\

          ggg.h

          fff.h

        module_a\

          a.h

          ax.h

          axx.h

        module_b\

          b.h

          bx.h

          bxx.h

  我平时使用的Makefile可以从这里下载到(持续更新,demo中会有更全面的例子),里面随便一个C++demo下载下来就有Makefile,可以参考(我不是很深入的了解Makefile,所以写的可能有些啰嗦、、不过好歹能用。。。),下面贴上我自己平时用的Makefile模板(配合Visual Studio的NMAKE程序,换到linux下其实也就是改改compiler和linker还有一些其他操作系统相关的指令就能用,差不太多)

  下面提供一个demo及其Makefile

  首先是Windows下的Makefile,适用于NMAKE程序,然后给出LINUX下的Makefile适用于GNU MAKE程序

  点此下载demo文件夹(注意,ZThread的.lib文件或者.a文件就不提供了,在Windows下,建议命名为ZThread.lib(只要跟Makefile里的名字相同就行);在Linux下,命名为libZThread.a,在Makefile中用-lZThread选项来代表这个文件,注意,文件名的前缀lib是不可缺少的。)

  注意:如果你的Makefile或者其他文件是用Windows下的编辑器写的,然后用U盘拷贝到linux下使用,不一定能被linux的编辑器正确解释(不同的系统编码啊,字节安排什么的不太一样),所以经常可能编译啊读取什么的出莫名其妙的错误,所以最好是在linux下新建文件并手动拷贝过去,比如说给你Makefile是在Windows下写的,拷到linux系统上一运行make,给你报错:Makefile:xxx: *** missing seperator. stop,其中xxx是你Makefile的最后一行行号。这种错误其实很简单,新建一个文件,把Makefile的内容复制粘贴进去,然后改名为Makefile,删掉原来的Makefile,就可以用了。

    GNU MAKE Makefile

 1 # compiler
 2 CC = g++
 3 # linker
 4 LINK = g++
 5 # libraries
 6 
 7 # The following 2 options specify library files /home/lqr/Documents/ZThread-2.3.2/lib/libZThread.a 
 8 # AND /home/lqr/Documents/531-SynchronizedOutput/lib/libSynchronizedOutput.a
 9 
10 # A -L<PATH_NAME> option specifies 1 search path
11 # A -l<LIBRARY_NAME> option specifies 1 library file to search in all
12 # the paths specified by -L options and system's default search paths
13 
14 # A library file's name is something like libLIBRARY_NAME.a
15 # note that the 'lib' prefix must exist for -l<LIBRARY_NAME> to work
16 # properly
17 
18 # -lpthread specifies pthread, which is an operating system's library,
19 # it's one of the basis for ZThread library
20 
21 LIBPATH_ZTHREAD = -L/home/lqr/Documents/ZThread-2.3.2/lib
22 LIBPATH_SYNC_OUTPUT = -Llib
23 
24 # Unlike Microsoft's LINK program, the GNU linker searches object
25 # files in a sequential (even if not strictly sequential) manner, you
26 # must place LIBFILES in a proper order, so you cannot put those -l
27 # options right next to the above -L options like I did in the
28 # Makefile for Microsoft's NMAKE program. Otherwise you'll get undefined reference error.
29 
30 LIBFILES_ZTHREAD = -lZThread -lpthread
31 LIBFILES_SYNC_OUTPUT = -lSynchronizedOutput
32 
33 # headers
34 
35 # One -I<PATH_NAME> specifies 1 path name to search for header files,
36 # it works for both #include"" and #include<> commands
37 
38 HEADER_PATH = -I/home/lqr/Documents/ZThread-2.3.2/include -Iinclude
39 
40 # options
41 
42 COMPILATION_ONLY = -c
43 C_OUT = -o
44 L_OUT = -o
45 
46 # Some ZThread's code are old-fashioned and may not be accepted by modern compilers
47 FPERMISSIVE = -fpermissive
48 
49 # targets
50 
51 bin/test.exe: bin lib/SynchronizedOutput.a obj/SynchronizedOutputTask.o obj/NormalTask.o obj/Task.o obj/main.o
52     $(LINK) $(LIBPATH_ZTHREAD) $(LIBPATH_SYNC_OUTPUT) $(L_OUT) bin/test.exe obj/main.o obj/SynchronizedOutputTask.o obj/NormalTask.o obj/Task.o $(LIBFILES_ZTHREAD) $(LIBFILES_SYNC_OUTPUT)
53     
54 lib/SynchronizedOutput.a: lib obj obj/SynchronizedOutput.o
55     ar -r lib/libSynchronizedOutput.a obj/SynchronizedOutput.o
56 
57 obj/SynchronizedOutput.o: src/SynchronizedOutput.cpp include/SynchronizedOutput.h
58     $(CC) $(HEADER_PATH) $(COMPILATION_ONLY) $(FPERMISSIVE) src/SynchronizedOutput.cpp $(C_OUT) obj/SynchronizedOutput.o
59 
60 obj/main.o: src/main.cpp include/SynchronizedOutputTask.h include/NormalTask.h include/Task.h include/SynchronizedOutput.h
61     $(CC) $(HEADER_PATH) $(COMPILATION_ONLY) src/main.cpp $(C_OUT) obj/main.o
62 
63 obj/SynchronizedOutputTask.o: src/SynchronizedOutputTask.cpp include/SynchronizedOutputTask.h include/SynchronizedOutput.h
64     $(CC) $(HEADER_PATH) $(COMPILATION_ONLY) src/SynchronizedOutputTask.cpp $(C_OUT) obj/SynchronizedOutputTask.o
65     
66 obj/NormalTask.o: src/NormalTask.cpp include/NormalTask.h
67     $(CC) $(HEADER_PATH) $(COMPILATION_ONLY) src/NormalTask.cpp $(C_OUT) obj/NormalTask.o
68 
69 obj/Task.o: src/Task.cpp include/Task.h
70     $(CC) $(HEADER_PATH) $(COMPILATION_ONLY) $(FPERMISSIVE) src/Task.cpp $(C_OUT) obj/Task.o
71     
72 # folders
73 
74 bin:
75     mkdir bin
76 
77 obj:
78     mkdir obj
79     
80 lib:
81     mkdir lib
82     
83 # clean
84 # bin, lib, obj folders
85 
86 .PHONY: clean
87 clean:
88     -rm -r -f bin
89     -rm -r -f lib
90     -rm -r -f obj

 

 

  NMAKE Makefile

 1 # compiler
 2 CC = cl
 3 # linker
 4 LINK = link
 5 # libraries
 6 LIB_ZTHREAD = /LIBPATH:E:\cppwksp\zthreaddemo_win\libs\zthread ZThread_win32.lib
 7 LIB_SYNC_OUTPUT = /LIBPATH:lib SynchronizedOutput.lib
 8 # headers
 9 HEADER_PATH = /I E:\cppwksp\zthreaddemo_win\include /I include
10 # options
11 EHSC = /EHsc
12 COMPILATION_ONLY = /c
13 C_OUT = /Fo:
14 L_OUT = /OUT:
15 # compiler & linker debug option, to disable debug, replace '/Zi' & '/DEBUG' with empty strings
16 # C_DEBUG = /Zi
17 # L_DEBUG = /DEBUG
18 C_DEBUG = 
19 L_DEBUG = 
20 # targets
21 
22 bin\test.exe: bin lib\SynchronizedOutput_win32.lib obj\SynchronizedOutputTask.obj obj\NormalTask.obj obj\Task.obj obj\main.obj
23     $(LINK) $(L_DEBUG) $(LIB_ZTHREAD) $(LIB_SYNC_OUTPUT) $(L_OUT)bin\test.exe obj\main.obj obj\SynchronizedOutputTask.obj obj\NormalTask.obj obj\Task.obj
24     
25 lib\SynchronizedOutput_win32.lib: lib obj obj\SynchronizedOutput.obj
26     LIB $(L_OUT)lib\SynchronizedOutput_win32.lib obj\SynchronizedOutput.obj
27 
28 obj\SynchronizedOutput.obj: src\SynchronizedOutput.cpp include\SynchronizedOutput.h
29     $(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\SynchronizedOutput.cpp $(C_OUT)obj\SynchronizedOutput.obj
30 
31 obj\main.obj: src\main.cpp include\SynchronizedOutputTask.h include\NormalTask.h include\Task.h
32     $(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\main.cpp $(C_OUT)obj\main.obj
33 
34 obj\SynchronizedOutputTask.obj: src\SynchronizedOutputTask.cpp include\SynchronizedOutputTask.h include\Task.h include\SynchronizedOutput.h
35     $(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\SynchronizedOutputTask.cpp $(C_OUT)obj\SynchronizedOutputTask.obj
36     
37 obj\NormalTask.obj: src\NormalTask.cpp include\NormalTask.h include\Task.h
38     $(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\NormalTask.cpp $(C_OUT)obj\NormalTask.obj
39 
40 obj\Task.obj: src\Task.cpp include\Task.h
41     $(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\Task.cpp $(C_OUT)obj\Task.obj
42     
43 # folders
44 
45 bin:
46     mkdir bin
47 
48 obj:
49     mkdir obj
50     
51 lib:
52     mkdir lib
53     
54 # clean
55 # bin, lib, obj folders and pdb files
56 
57 .PHONY: clean
58 clean:
59     -rmdir /s /q bin
60     -rmdir /s /q lib
61     -rmdir /s /q obj
62     -del *.pdb

 

  关于Makefile,我写了一篇笔记很重要,点此查看

另外,如果你希望在windows下编译的时候用一个文件叫Makefile.win32,在linux下编译的时候用另一个文件叫Makefile.linux,那么下面是典型的Makefile.linux的例子。(点此下载DEMO

# compiler
CC = g++
# linker
LINK = g++
# libraries
LIBPATH_ZTHREAD = -L/home/lqr/Documents/ZThread-2.3.2/lib
LIBFILE_ZTHREAD = -lZThread -lpthread
# headers
HEADER_PATH = -I/home/lqr/Documents/ZThread-2.3.2/include -Iinclude -I/home/lqr/Documents/ZJ/548-TestTQueue-linux/include
# options

COMPILATION_ONLY = -c
C_OUT = -o
L_OUT = -o

# Some ZThread's code are old-fashioned and may not be accepted by modern compilers
FPERMISSIVE = -fpermissive

obj = linux/obj
bin = linux/bin

# targets

$(bin)/test.exe: linux $(obj)/main.o $(obj)/Car.o $(obj)/EngineRobot.o $(obj)/Cradle.o $(obj)/DriveTrainRobot.o $(obj)/WheelRobot.o $(obj)/Director.o $(obj)/ChassisBuilder.o $(obj)/Reporter.o
    $(LINK) $(L_DEBUG) $(LIBPATH_ZTHREAD) $(L_OUT) $(bin)/test.exe $(obj)/main.o $(obj)/EngineRobot.o $(obj)/Cradle.o $(obj)/DriveTrainRobot.o $(obj)/WheelRobot.o $(obj)/Director.o $(obj)/ChassisBuilder.o $(obj)/Reporter.o $(obj)/Car.o $(LIBFILE_ZTHREAD)

$(obj)/main.o: src/main.cpp include/EngineRobot.h include/Cradle.h include/DriveTrainRobot.h include/WheelRobot.h include/Director.h include/ChassisBuilder.h include/Reporter.h include/typedefs.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/main.cpp $(C_OUT) $(obj)/main.o

$(obj)/EngineRobot.o: src/EngineRobot.cpp include/EngineRobot.h include/typedefs.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/EngineRobot.cpp $(C_OUT) $(obj)/EngineRobot.o
    
$(obj)/DriveTrainRobot.o: src/DriveTrainRobot.cpp include/DriveTrainRobot.h include/typedefs.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/DriveTrainRobot.cpp $(C_OUT) $(obj)/DriveTrainRobot.o

$(obj)/WheelRobot.o: src/WheelRobot.cpp include/WheelRobot.h include/typedefs.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/WheelRobot.cpp $(C_OUT) $(obj)/WheelRobot.o

    
$(obj)/Cradle.o: src/Cradle.cpp include/Cradle.h include/Car.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/Cradle.cpp $(C_OUT) $(obj)/Cradle.o
    
$(obj)/Director.o: src/Director.cpp include/Director.h include/typedefs.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/Director.cpp $(C_OUT) $(obj)/Director.o

$(obj)/ChassisBuilder.o: src/ChassisBuilder.cpp include/ChassisBuilder.h include/typedefs.h include/Car.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/ChassisBuilder.cpp $(C_OUT) $(obj)/ChassisBuilder.o
    
$(obj)/Car.o: src/Car.cpp include/Car.h
    $(CC) $(HEADER_PATH) $(COMPILATION_ONLY) src/Car.cpp $(C_OUT) $(obj)/Car.o
    
$(obj)/Reporter.o: src/Reporter.cpp include/Reporter.h include/typedefs.h
    $(CC) $(FPERMISSIVE) $(HEADER_PATH) $(COMPILATION_ONLY) src/Reporter.cpp $(C_OUT) $(obj)/Reporter.o

# folders

linux:
    mkdir linux
    cd linux; mkdir bin; mkdir obj
    
# clean

.PHONY: clean
clean:
    -rm -r -f linux

 

下面给一个在windows下使用的简单的demo的Makefile(就是说你只有一个cpp文件,我一般命名为main.cpp,用来进行一些小的demo的验证啥的)

CC = cl
DEBUG = /Zi

target:
	$(CC) $(DEBUG) main.cpp

clean:
	-del *.obj
	-del *.pdb
	-del *.exe
	-del *.ilk

 linux:

CC = g++

target: $(CC) main.cpp clean: rm -f *.o rm -f *.out

 如果上面的makefile不够用的话,也可以用这个版本(也是适用于只有一个cpp文件的demo),这个makefile的demo也可以在我上面上传的文件夹中找到:

CC = cl
LINK = link

# options
EHSC = /EHsc
COMPILATION_ONLY = /c
C_OUT = /Fo:
L_OUT = /OUT:
# compiler & linker debug option, to disable debug, replace '/Zi' & '/DEBUG' with empty strings
C_DEBUG = /Zi
L_DEBUG = /DEBUG
# C_DEBUG = 
# L_DEBUG = 

# libraries
LIBPATH_TESTSUITE = /LIBPATH:E:\cppwksp\thinkingincppvol2\demo\72-TestSuite\lib
LIBFILE_TESTSUITE = TestSuite.lib

# headers
HEADER_PATH = /I E:\cppwksp\thinkingincppvol2\demo\72-TestSuite\include

target:
	$(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) main.cpp $(C_OUT)main.obj
	$(LINK) $(L_DEBUG) $(LIBPATH_TESTSUITE) $(L_OUT)test.exe main.obj $(LIBFILE_TESTSUITE)

clean:
	-del *.obj
	-del *.pdb
	-del *.exe
	-del *.ilk

 

1、头文件的#include顺序:自己写的头文件、第三方工具的头文件、标准头文件,尽量从上到下这样安排顺序

   头文件一定要写上#ifndef xxx #define xxx #endif的header guard

   头文件中除了template和inline以外,都只写declaration不要把implementation代码写在头文件里,免得xxx redefined错误,保持一个好的习惯

2、头文件里不要包含:using指令和using namespace指令

  头文件中不要初始化static member,避免xxx redefined错误,放到cpp文件中去初始化

3、如果你有一个class,尽量为这个class建立一个单独的header文件和cpp文件,需要隐藏实现细节的时候除外

4、待补充。。。

posted @ 2015-01-19 00:10  rldts  阅读(462)  评论(0编辑  收藏  举报