大家帮我看看这个Makefile写的还能用吧

mLee79 2011-01-02 12:57:00
现在的IDE的项目管理感觉是越来越烂了, 上周末不知道咋回事突然对Makefile感兴趣了,决定自己弄一个玩玩...
于是现学现卖, 主要照抄 Android NDK 和 How to Write Makefile , 弄了个个人感觉还蛮好用的.
主要功能如下:

1) 只要几行代码就可以管理一个项目( 静态库, 动态库, 可执行程序, 单元测试代码). 自动生成依赖关系..
2) 支持 C CPP ASM 代码的编译.
3) 方便定义自己的预处理器, 要加上 E-SQL , CUDA 啥类型的特别点的预处理器还是比较容易的. 特别适合喜欢折腾的.
4) 即将实现的各个不同平台, 不同目标系统下的编译配置.

已经完成的: cygwin - gcc 下差不多完工 ( 汇编我只喜欢 yasm , 喜欢其他汇编器的自己改下 ) , 正在进行的 linux-i386 , linux-amd64 , linux-amd64-i386 , cygwin - cl-i386 , cygwin - cl-amd64 , cygwin - arm-linux-gcc , linux - arm-linux-gcc ... 方便你在各个不同的平台下测试你的代码...

以后我还会做的:
1) 一个正则表达式->DFA的预处理器, 方便你写出高效的,可重入的词法分析代码.
2) 一个 LALR(1) 的预处理器, 它会为你生成一个下推自动机..

喜欢的可以在这 checkout 代码:
svn co https://x4c.googlecode.com/svn/misc/xMAKE/trunk

...全文
346 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
老邓 2011-01-30
  • 打赏
  • 举报
回复
还可以使用CMake,非常棒的跨平台工程管理工具。
例子:
project(demo_01)
cmake_minimum_required(VERSION 2.8)
set(SRC_LIST main.c)
set(CMAKE_BUILD_TYPE Release)
include_directories(..)
add_executable(test ${SRC_LIST})
mLee79 2011-01-12
  • 打赏
  • 举报
回复
又加上 android 的编译配置, 可以直接生成 android 下的静态库/动态库/可执行文件, 现在代码放在:

svn co http://x4c.googlecode.com/svn/branches/liang.li/2011/x4c-new-trunk/

在以后一个合适的时候, 我会把它移到 trunk ....

好像我基本就只在这些平台下编译代码, 差不多够我用了...
xunxun 2011-01-04
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 mlee79 的回复:]

1. 不同平台需要不同的源文件怎么办?
我上面弄的小例子里已经有了, 比如
$(call x4c_add_all_S_source_files_under_recursive,$(LOCAL_PATH)/asmfiles/$(X4C_ARCH))
它将根据 ARCH 的定义添加不同的平台相关的代码 ...

2. 我不是加了个 filter 的么, 你为 .rc 文件类型定制个过滤器……
[/Quote]
跨平台时都是写一些宏交给configure或cmake来进行判断的,检测什么平台就加什么宏,这样不需要的代码块就跳过去了,当然lz这样写亦可。
mLee79 2011-01-04
  • 打赏
  • 举报
回复
1. 不同平台需要不同的源文件怎么办?
我上面弄的小例子里已经有了, 比如
$(call x4c_add_all_S_source_files_under_recursive,$(LOCAL_PATH)/asmfiles/$(X4C_ARCH))
它将根据 ARCH 的定义添加不同的平台相关的代码 ...

2. 我不是加了个 filter 的么, 你为 .rc 文件类型定制个过滤器, 然后把 .rc 加入到工程就可以了, 同样的 .idl .def 等等都这样处理...
3. 同样的, 我们可以为 测试文件制定特别的规则, 比如要么放在特定目录下, 要么有特定的命名方式... 写个过滤器轻松处理...
4. 预编译头文件命名应该很特别, 写 filter 应该不难...
5. 我会建立一个 Makefile 类型的工程, 然后要求他安装 cygwin ...
老邓 2011-01-04
  • 打赏
  • 举报
回复
呵呵,我现在业余爱好时喜欢写跨平台程序。
自动生成有自动生成的好处,但坏处也是很明显的。

1. 不同平台需要不同的源文件怎么办?
2. 一些平台专用文件怎么办(rc,res)?
3. 库下面还包含一些测试文件,而测试文件不属于工程怎么办?
4. 预处理头文件如何支持?
5. 如果是Windows程序,客户需要你提供VS的工程怎么办(当然,不开发Windows程序就不必考虑这个问题了)?

这个世界上除了Windows程序,可以写的东西确实很多。
但Windows桌面系统70%以上的占有率也是不争的事实。
mLee79 2011-01-04
  • 打赏
  • 举报
回复
你觉得修改文件, 添加代码以后还得重新生成 makefile 不无聊么... 一个几千个文件的项目生成一次makefile要很久的,老大... 你不觉得就专心写代码, 其他的都自动生成更好么...
世界上除了 windows 程序, 可以写的东西还很多... 偶已经7年没写过纯windows程序了...

老邓 2011-01-04
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 mlee79 的回复:]

在我这地方, cygwin / linux 的普及程度远比 qt 高的多, 这附近没有人有 qmake ...
你不觉得每改一次 .pro 就要运行 qmake 生成一次很繁琐么... 我的是 Makefile 写好后, 不管加了多少源文件, 多少头文件, 都不用修改任何的 makefile , project file , 它都会自动的为你生成一切...
还有, 只生产一次的依赖关系有什么……
[/Quote]
一个道理:一个qmake加上makespec,压缩后连2MB都不到!
加个脚本或者批处理,是完全可以自动生成makefile的。
另外,QtCreator也是一个很不错的编辑器。
即使不是开发Qt项目,也是可以的。

编译、调试、运行,鼠标点击一下就可以了。
如果你只用VIM,那么还可以通过fakevim插件来模拟vim操作。

纯Windows程序开发,没有使用cygwin的。
mLee79 2011-01-04
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 zhao4zhong1 的回复:]

小心哪天某个无良编辑器把你make文件中的硬Tab自动替换为软Tab!
[/Quote]

虽然很多lr建议用空格代替tab排版, 但偶还是坚持使用tab...
还有, 按偶的写法, 各个子 project file 里是不需要使用 tab 的, 而 makefile 是基本上不用改的, 哈哈...


mLee79 2011-01-04
  • 打赏
  • 举报
回复
在我这地方, cygwin / linux 的普及程度远比 qt 高的多, 这附近没有人有 qmake ...
你不觉得每改一次 .pro 就要运行 qmake 生成一次很繁琐么... 我的是 Makefile 写好后, 不管加了多少源文件, 多少头文件, 都不用修改任何的 makefile , project file , 它都会自动的为你生成一切...
还有, 只生产一次的依赖关系有什么用, 难道我修改了代码后还要手动的重新生成新的Makefile么, 不能动态的生成依赖关系我觉得比完全仅仅使用 .c.o 的依赖关系更加恶劣 ...



赵4老师 2011-01-04
  • 打赏
  • 举报
回复
小心哪天某个无良编辑器把你make文件中的硬Tab自动替换为软Tab!
za363k6 2011-01-04
  • 打赏
  • 举报
回复
我看行
老邓 2011-01-04
  • 打赏
  • 举报
回复
写了一个简单的pro文件:

CONFIG -= \
qt

LIBS += \
-lkernel32 \
-luser32

SOURCES += \
main.cpp \
testclass.cpp

HEADERS += \
testclass.h \
pch.h


将qmake和makespec提取出来(拷贝qmake和makespec目录到工程所在路径,或置PATH环境变量中),执行:
qmake -o Makefile haha.pro -spec win32-msvc2010


不同的spec针对不同的编译器。
例如:
qmake -o Makefile haha.pro -spec win32-g++

则生成GCC的Makefile。

编译时,或者nmake,或者make,即可针对不同编译器编译。
由于qmake可以自动生成依赖,所以针对VC编译器中最繁琐的一环就不再存在了。

生成的Makefile如下 :
#############################################################################
# Makefile for building: haha
# Generated by qmake (2.01a) (Qt 4.7.1) on: ?? ?? 4 15:11:43 2011
# Project: haha.pro
# Template: app
# Command: d:\DengYC\QtVC\qt\bin\qmake -spec mkspecs\win32-g++ -o Makefile haha.pro
#############################################################################

first: release
install: release-install
uninstall: release-uninstall
MAKEFILE = Makefile
QMAKE = d:\DengYC\QtVC\qt\bin\qmake
DEL_FILE = del
CHK_DIR_EXISTS= if not exist
MKDIR = mkdir
COPY = copy /y
COPY_FILE = $(COPY)
COPY_DIR = xcopy /s /q /y /i
INSTALL_FILE = $(COPY_FILE)
INSTALL_PROGRAM = $(COPY_FILE)
INSTALL_DIR = $(COPY_DIR)
DEL_FILE = del
SYMLINK =
DEL_DIR = rmdir
MOVE = move
CHK_DIR_EXISTS= if not exist
MKDIR = mkdir
SUBTARGETS = \
release \
debug

release: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release
release-make_default: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release
release-make_first: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release first
release-all: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release all
release-clean: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release clean
release-distclean: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release distclean
release-install: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release install
release-uninstall: $(MAKEFILE).Release FORCE
$(MAKE) -f $(MAKEFILE).Release uninstall
debug: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug
debug-make_default: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug
debug-make_first: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug first
debug-all: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug all
debug-clean: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug clean
debug-distclean: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug distclean
debug-install: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug install
debug-uninstall: $(MAKEFILE).Debug FORCE
$(MAKE) -f $(MAKEFILE).Debug uninstall

Makefile: haha.pro mkspecs/win32-g++/qmake.conf mkspecs/features/qt_functions.prf \
mkspecs/features/qt_config.prf \
mkspecs/features/exclusive_builds.prf \
mkspecs/features/default_pre.prf \
mkspecs/features/win32/default_pre.prf \
mkspecs/features/release.prf \
mkspecs/features/debug_and_release.prf \
mkspecs/features/default_post.prf \
mkspecs/features/win32/default_post.prf \
mkspecs/features/warn_on.prf \
mkspecs/features/win32/windows.prf \
mkspecs/features/win32/thread_off.prf \
mkspecs/features/win32/stl_off.prf \
mkspecs/features/win32/exceptions_off.prf \
mkspecs/features/win32/rtti_off.prf \
mkspecs/features/resources.prf \
mkspecs/features/uic.prf \
mkspecs/features/yacc.prf \
mkspecs/features/lex.prf \
mkspecs/features/include_source_dir.prf
$(QMAKE) -spec mkspecs\win32-g++ -o Makefile haha.pro
mkspecs\features\qt_functions.prf:
mkspecs\features\qt_config.prf:
mkspecs\features\exclusive_builds.prf:
mkspecs\features\default_pre.prf:
mkspecs\features\win32\default_pre.prf:
mkspecs\features\release.prf:
mkspecs\features\debug_and_release.prf:
mkspecs\features\default_post.prf:
mkspecs\features\win32\default_post.prf:
mkspecs\features\warn_on.prf:
mkspecs\features\win32\windows.prf:
mkspecs\features\win32\thread_off.prf:
mkspecs\features\win32\stl_off.prf:
mkspecs\features\win32\exceptions_off.prf:
mkspecs\features\win32\rtti_off.prf:
mkspecs\features\resources.prf:
mkspecs\features\uic.prf:
mkspecs\features\yacc.prf:
mkspecs\features\lex.prf:
mkspecs\features\include_source_dir.prf:
qmake: qmake_all FORCE
@$(QMAKE) -spec mkspecs\win32-g++ -o Makefile haha.pro

qmake_all: FORCE

make_default: release-make_default debug-make_default FORCE
make_first: release-make_first debug-make_first FORCE
all: release-all debug-all FORCE
clean: release-clean debug-clean FORCE
distclean: release-distclean debug-distclean FORCE
-$(DEL_FILE) Makefile

check: first
FORCE:

$(MAKEFILE).Release: Makefile
$(MAKEFILE).Debug: Makefile


以Release为例:
#############################################################################
# Makefile for building: haha
# Generated by qmake (2.01a) (Qt 4.7.1) on: ?? ?? 4 15:11:43 2011
# Project: haha.pro
# Template: app
#############################################################################

####### Compiler, tools and options

CC = gcc
CXX = g++
DEFINES = -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NEEDS_QMAIN -DQT_NO_DYNAMIC_CAST
CFLAGS = -O2 -Wall $(DEFINES)
CXXFLAGS = -O2 -Wall -fno-exceptions -fno-rtti $(DEFINES)
INCPATH = -I"mkspecs\win32-g++"
LINK = g++
LFLAGS = -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-s -Wl,-subsystem,windows
LIBS = -lkernel32 -luser32
QMAKE = d:\DengYC\QtVC\qt\bin\qmake
IDC = d:\DengYC\QtVC\qt\bin\idc.exe
IDL = midl
ZIP = zip -r -9
DEF_FILE =
RES_FILE =
COPY = copy /y
COPY_FILE = $(COPY)
COPY_DIR = xcopy /s /q /y /i
DEL_FILE = del
DEL_DIR = rmdir
MOVE = move
CHK_DIR_EXISTS= if not exist
MKDIR = mkdir
INSTALL_FILE = $(COPY_FILE)
INSTALL_PROGRAM = $(COPY_FILE)
INSTALL_DIR = $(COPY_DIR)

####### Output directory

OBJECTS_DIR = release

####### Files

SOURCES = main.cpp \
testclass.cpp
OBJECTS = release/main.o \
release/testclass.o
DIST =
QMAKE_TARGET = haha
DESTDIR = release\ #avoid trailing-slash linebreak
TARGET = haha.exe
DESTDIR_TARGET = release\haha.exe

####### Implicit rules

.SUFFIXES: .cpp .cc .cxx .c

.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<

.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<

.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<

.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<

####### Build rules

first: all
all: Makefile.Release $(DESTDIR_TARGET)

$(DESTDIR_TARGET): $(OBJECTS)
$(LINK) $(LFLAGS) -o $(DESTDIR_TARGET) $(OBJECTS) $(LIBS)


qmake: FORCE
@$(QMAKE) -spec mkspecs\win32-g++ -o Makefile.Release haha.pro

dist:
$(ZIP) haha.zip $(SOURCES) $(DIST) haha.pro mkspecs\features\qt_functions.prf mkspecs\features\qt_config.prf mkspecs\features\exclusive_builds.prf mkspecs\features\default_pre.prf mkspecs\features\win32\default_pre.prf mkspecs\features\release.prf mkspecs\features\debug_and_release.prf mkspecs\features\default_post.prf mkspecs\features\win32\default_post.prf mkspecs\features\build_pass.prf mkspecs\features\warn_on.prf mkspecs\features\win32\windows.prf mkspecs\features\win32\thread_off.prf mkspecs\features\win32\stl_off.prf mkspecs\features\win32\exceptions_off.prf mkspecs\features\win32\rtti_off.prf mkspecs\features\resources.prf mkspecs\features\uic.prf mkspecs\features\yacc.prf mkspecs\features\lex.prf mkspecs\features\include_source_dir.prf RESOURCES FORMS IMAGES YACCSOURCES YACCSOURCES LEXSOURCES

clean: compiler_clean
-$(DEL_FILE) release\main.o release\testclass.o

distclean: clean
-$(DEL_FILE) $(DESTDIR_TARGET)
-$(DEL_FILE) Makefile.Release

check: first

compiler_rcc_make_all:
compiler_rcc_clean:
compiler_uic_make_all:
compiler_uic_clean:
compiler_image_collection_make_all: qmake_image_collection.cpp
compiler_image_collection_clean:
-$(DEL_FILE) qmake_image_collection.cpp
compiler_yacc_decl_make_all:
compiler_yacc_decl_clean:
compiler_yacc_impl_make_all:
compiler_yacc_impl_clean:
compiler_lex_make_all:
compiler_lex_clean:
compiler_clean:



####### Compile

release/main.o: main.cpp testclass.h \
pch.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release\main.o main.cpp

release/testclass.o: testclass.cpp testclass.h \
pch.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release\testclass.o testclass.cpp

####### Install

install: FORCE

uninstall: FORCE

FORCE:


老邓 2011-01-04
  • 打赏
  • 举报
回复
不是谁都有cygwin环境,再说了,cygwin环境比msys臃肿多了。
要用Unix的shell,不如基于msys。

对于跨平台的makefile需求(工程管理),我更倾向于使用qmake。
如果客户需要,还可以生成VS的工程项目。
老邓 2011-01-03
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 mlee79 的回复:]

linux 下的都差不多了, i386 amd64 的都该能行... 下面弄 M$VC 下的...
唉, 这个生成依赖关系麻烦了, 要不要自己写个小工具弄, 还是直接用 gcc 生成算了...
[/Quote]
进来主要就是看如何解决VC的依赖关系的。
这个目前我所知的有两个途径:
1. 自己写工具生成依赖,例如我之前写过一个NMaker,开源的,不过我的博客挂了,代码可能找不到了。
2. 另一个,使用VC的最小生成选项,/Gm,详见:http://www.xuyibo.org/article/78.htm
mLee79 2011-01-03
  • 打赏
  • 举报
回复
整个 Makefile 很多都是用 bash shell 的命令, cygwin/mingw 都有了, 怎么会没 gcc ...
M$的shell只能说过于幼稚, 实在是没办法用 ... 继续使用 M$ 环境的原因是 VA 实在无法割舍...
基本上我不考虑在没有 gcc , bash , perl , flex , bison 的环境下干活, 如果是在 i386/amd64 并且需要汇编 yasm 也是必要的, gas 的错误提示实在让人有些崩溃...

弄这个Makefile的原因是为了编写一次代码和Makefile就可以在几乎所有的 *nix 环境下编译以及交叉编译, 弄一个 windows 下的配置文件只是我不想再为 M$VC 创建一个工程文件...


老邓 2011-01-03
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 mlee79 的回复:]
那种简单生成依赖关系的, 用脚本应该没几行就好了...
[/Quote]
还是环境问题。
不是什么环境,脚本都可以大展拳脚的。
尤其是Windows平台。
如果你的Makefile只面向Unix,则无所谓了。
老邓 2011-01-03
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 mlee79 的回复:]

唉, 还是弄成用 gcc 做依赖关系了, 看起来好丑, 限制也多了, 不过确实能用...
[/Quote]
不是什么平台都有GCC的,尤其是Windows平台。
如果依赖关系还要靠GCC来生成,代价太大了,也不通用。

Code::Blocks中有一个depend的lib,用于生成依赖关系的。
如果感兴趣,可以看一下。
mLee79 2011-01-03
  • 打赏
  • 举报
回复
唉, 还是弄成用 gcc 做依赖关系了, 看起来好丑, 限制也多了, 不过确实能用...

mLee79 2011-01-03
  • 打赏
  • 举报
回复
你的代码我应该看过, 应该不大合适, 那种简单生成依赖关系的, 用脚本应该没几行就好了...
最好的办法可能是直接用 gcc 了, 只是看起来很异怪... 移植一个 cpp 搞可能合适些...
不过还是暂时先用 .c.o 的依赖对付着...

mLee79 2011-01-02
  • 打赏
  • 举报
回复
先占下沙发...
加载更多回复(9)

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧