【持续更新】总结: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.
# 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
更新:
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、待补充。。。