我想知道是否有Makefile
s(make
)和CMakeLists.txt
(cmake
)的示例代码,它们都做同样的事情(唯一的区别是那个写在make
中,另一个写在cmake
中。
我尝试寻找'cmake vs make',但我从未发现任何代码比较。理解这些差异真的很有帮助,即使仅仅是为了一个简单的案例。
答案 0 :(得分:108)
以下Makefile从源代码构建名为prog
的可执行文件
prog1.c, prog2.c, prog3.c and main.c
。 prog
与libmystatlib.a
相关联
和libmydynlib.so
这些都是从源代码构建的。此外,prog
使用
libstuff.a
中的库stuff/lib
及其stuff/include
中的标题。该
Makefile默认构建一个发布目标,但也提供了一个调试目标:
#Makefile
CC = gcc
CPP = g++
RANLIB = ar rcs
RELEASE = -c -O3
DEBUG = -c -g -D_DEBUG
INCDIR = -I./stuff/include
LIBDIR = -L./stuff/lib -L.
LIBS = -lstuff -lmystatlib -lmydynlib
CFLAGS = $(RELEASE)
PROGOBJS = prog1.o prog2.o prog3.o
prog: main.o $(PROGOBJS) mystatlib mydynlib
$(CC) main.o $(PROGOBJS) $(LIBDIR) $(LIBS) -o prog
debug: CFLAGS=$(DEBUG)
debug: prog
mystatlib: mystatlib.o
$(RANLIB) libmystatlib.a mystatlib.o
mydynlib: mydynlib.o
$(CPP) -shared mydynlib.o -o libmydynlib.so
%.o: %.c
$(CC) $(CFLAGS) $(INCDIR) $< -o $@
%.o: %.cpp
$(CPP) $(CFLAGS) $(INCDIR) -fPIC $< -o $@
这是一个CMakeLists.txt
(几乎)完全相同,有一些注释要强调
与Makefile的相似之处:
#CMakeLists.txt
cmake_minimum_required(VERSION 2.8) # stuff not directly
project(example) # related to building
include_directories(${CMAKE_SOURCE_DIR}/stuff/include) # -I flags for compiler
link_directories(${CMAKE_SOURCE_DIR}/stuff/lib) # -L flags for linker
set(PROGSRC prog1.c prog2.c prog3.c) # define variable
add_executable(prog main.c ${PROGSRC}) # define executable target prog, specify sources
target_link_libraries(prog mystatlib mydynlib stuff) # -l flags for linking prog target
add_library(mystatlib STATIC mystatlib.c) # define static library target mystatlib, specify sources
add_library(mydynlib SHARED mydynlib.cpp) # define shared library target mydynlib, specify sources
#extra flags for linking mydynlib
set_target_properties(mydynlib PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
#alternatively:
#set_target_properties(mydynlib PROPERTIES COMPILE_FLAGS "-fPIC")
在这个简单的例子中,最重要的区别是:
CMake识别哪些编译器用于哪种源。它,它 为每种类型的目标调用正确的命令序列。因此,那里 没有明确规定命令,如$(CC)...,$(RANLIB)......等等。
处理包含头文件,库等的所有常用编译器/链接器标志。 由独立于平台/构建系统的命令替换。
通过将变量CMAKE_BUILD_TYPE设置为“Debug”来包含调试标志,
或者在调用程序时将其传递给CMake:cmake -DCMAKE_BUILD_TYPE:STRING=Debug
。
CMake还提供独立于平台的'-fPIC'标志(通过
POSITION_INDEPENDENT_CODE属性)和许多其他人。仍然可以在CMake中手动实现更加模糊的设置以及在Makefile中实现(通过使用COMPILE_FLAGS
和类似的属性)。当然,当第三方时,CMake真正开始闪耀
库(如OpenGL)以可移植的方式包含在内。
如果使用Makefile,则构建过程只有一步,即在命令行键入
make
。对于CMake,有两个步骤:首先,您需要设置构建环境(通过在构建目录中键入cmake <source_dir>
或运行一些GUI客户端)。这会创建一个Makefile或类似的东西,具体取决于您选择的构建系统(例如,在Unix上使用或在Windows上使用VC ++或MinGW + Msys)。构建系统可以作为参数传递给CMake;但是,CMake根据您的系统配置做出合理的默认选择。其次,您在选定的构建系统中执行实际构建。
https://github.com/rhoelzel/make_cmake提供了来源和构建说明。
答案 1 :(得分:7)
抓住一些使用CMake作为其构建系统的软件(有很多开源项目可供选择)。获取源代码并使用CMake进行配置。阅读生成的makefile并享受。
要注意的是,这些工具不会一对一地映射。最明显的区别是CMake扫描不同文件(例如C头文件和源文件)之间的依赖关系,而make则将其留给makefile作者。
答案 2 :(得分:4)
如果此问题与Makefile
文件的示例CMakeList.txt
输出有关,请检查cmake-backend来源并生成一个此类Makefile
。如果它没有添加到@Roberto的回复中,我试图通过隐藏细节来简化它。
虽然Make
是规则和配方的灵活工具,但CMake
是一个抽象层,也添加了配置功能。</ p>
我的简单CMakeLists.txt
将如下所示,
cmake_minimum_required(VERSION 2.8)
project(example)
file(GLOB testapp_SOURCES *.cc)
add_executable(testapp ${testapp_SOURCES})
注意,CMake
隐藏how
构建可以完成。我们只指定what
是输入和输出。
CMakeLists.txt
包含由cmake
定义的函数调用列表。
在Makefile
中,rules and recipes
代替functions
。除function
之类的功能外,rules and recipes
还提供链接。我的简约Makefile
将如下所示,
-include "executable.mk"
TARGETS=testapp.bin
all:${TARGETS}
executable.mk
如下所示,
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
%.bin:$(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LIBS)
.PHONY: all clean
clean:
$(RM) $(OBJECTS) $(DEPS) $(TARGETS)
-include $(DEPS)
从头开始,我将从Makefile
开始,如下所示,
all: testapp.bin
testapp.bin:sourcea.o sourcb.o
$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LIBS)
.PHONY: all clean
clean:
$(RM) $(OBJECTS) testapp.bin
我从here获得了此片段并对其进行了修改。请注意,此文件中添加了一些隐式规则,可以在makefile-documentation中找到。一些隐含变量在这里也是相关的。
注意,Makefile
提供详细信息recipe
,显示how
可以完成构建。可以编写executable.mk
来保持在一个文件中定义的详细信息。通过这种方式,makefile可以像我之前所说的那样减少。
CMake
和Make
现在变得不高,在CMake
中我们可以设置如下的编译器标志,
set(CMAKE_C_FLAGS "-Wall")
请在CMake
文件中找到有关CMakeCache.txt
默认变量的更多信息。
上面的CMake
代码将等同于下面的Make
代码,
CFLAGS = -Wall
请注意,CFLAGS
是Make
中的内部变量,同样,CMAKE_C_FLAGS
是CMake
中的内部变量。
我们可以使用函数在cmake
中完成。
target_include_directories(testapp PRIVATE "myincludes")
list(APPEND testapp_LIBRARIES
mytest mylibrarypath
)
target_link_libraries(testapp ${testapp_LIBRARIES})
我们可以通过添加如下所示的行来添加include和库,
INCLUDES += -Imyincludes
LIBS += -Lmylibrarypath -lmytest
注意上面的这一行可以从auto-gen工具或pkg-config生成。 (尽管Makefile不依赖于自动配置工具)
通常可以使用config.h
函数生成一些auto-config
文件,就像configure_file
工具一样。编写自定义函数可以做更多的技巧。最后我们可以选择如下的配置,
cmake --build . --config "Release"
可以使用option
函数添加一些可配置选项。
如果以某种方式我们需要使用一些调试标志来编译它,我们可以调用make
之类的,
make CXXFLAGS=NDEBUG
我认为内部变量Makefile-rules
和CMake-functions
是比较良好的开端,祝你好运更多。