Cmake vs制作示例代码?

时间:2012-06-04 13:17:49

标签: makefile cmake

我想知道是否有Makefile s(make)和CMakeLists.txtcmake)的示例代码,它们都做同样的事情(唯一的区别是那个写在make中,另一个写在cmake中。

我尝试寻找'cmake vs make',但我从未发现任何代码比较。理解这些差异真的很有帮助,即使仅仅是为了一个简单的案例。

3 个答案:

答案 0 :(得分:108)

以下Makefile从源代码构建名为prog的可执行文件 prog1.c, prog2.c, prog3.c and main.cproglibmystatlib.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的回复中,我试图通过隐藏细节来简化它。

CMake功能

虽然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定义的函数调用列表。

(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可以像我之前所说的那样减少。

CMakeMake

中的内部变量

现在变得不高,在CMake中我们可以设置如下的编译器标志,

set(CMAKE_C_FLAGS "-Wall")

请在CMake文件中找到有关CMakeCache.txt默认变量的更多信息。 上面的CMake代码将等同于下面的Make代码,

CFLAGS = -Wall

请注意,CFLAGSMake中的内部变量,同样,CMAKE_C_FLAGSCMake中的内部变量。

在CMake中添加include和library路径

我们可以使用函数在cmake中完成。

target_include_directories(testapp PRIVATE "myincludes")
list(APPEND testapp_LIBRARIES
    mytest mylibrarypath
)
target_link_libraries(testapp ${testapp_LIBRARIES})

在Make

中添加include和库路径

我们可以通过添加如下所示的行来添加include和库,

INCLUDES += -Imyincludes
LIBS += -Lmylibrarypath -lmytest

注意上面的这一行可以从auto-gen工具或pkg-config生成。 (尽管Makefile不依赖于自动配置工具)

CMake configure / tweek

通常可以使用config.h函数生成一些auto-config文件,就像configure_file工具一样。编写自定义函数可以做更多的技巧。最后我们可以选择如下的配置,

cmake --build . --config "Release"

可以使用option函数添加一些可配置选项。

Makefile configure / tweak

如果以某种方式我们需要使用一些调试标志来编译它,我们可以调用make之类的,

make CXXFLAGS=NDEBUG

我认为内部变量Makefile-rulesCMake-functions是比较良好的开端,祝你好运更多。