Cmake 대 make 샘플 코드?


118

모든 샘플 코드가 있다면 궁금 해서요 Makefile의 ( make) 및 CMakeLists.txt( cmake) 모두 (유일한 차이점은 하나에 기록되어있는 같은 일을한다는 make와 다른 cmake).

'cmake vs make'를 찾아 보았지만 코드 비교를 찾지 못했습니다. 단순한 경우라도 차이점을 이해하는 것이 정말 도움이 될 것입니다.


20
+1 좋은 질문입니다. 내가 시작할 때 나도 cmake이것을 원했다. 그러나 기능이 서로 잘 매핑되지 않기 때문에 찾을 수 있을지 의문입니다. 당신이처럼 cmake행동 하려고하면 make, 당신은 자신을 미치게 만들 것입니다. 처음부터 시작하는 것이 가장 좋습니다. 에서 사소한 것은 make에 상당히 관련되어 cmake있으며 그 반대의 경우도 마찬가지입니다.
Ernest Friedman-Hill

1
@ ErnestFriedman-Hill에 대한 자세한 내용이 있습니까? 그래서 make그리고 cmake그들은 더 보완 대신 도구를 경쟁으로 볼 수 있어야 너무 별개?
Ehtesh Choudhury 2013

2
@Shurane-cmake는 자체적으로 아무것도 빌드하지 않습니다. Makefile (및 기타 유사한 빌드 스크립트)을 생성 한 다음 실행합니다. 따라서 cmake 파일을 작성할 때마다 명령을 생성 할 때 적용할지 빌드 할 때 적용해야할지 생각해야합니다. 예를 들어 빌드시 와일드 카드 파일 세트 복사와 같은 일부 작업 cp *.x $(OUTDIR)은 Makefile에 작성 하는 " "에 비해 매우 복잡 합니다. 아마도 나에게 가장 짜증나는 부분은 생성 된 메이크 디자인에 의해 완전히 이식성 및 유연성 (계속) 있다는 것입니다
어니스트 프리드먼 - 힐

1
(계속) Makefile을 다시 생성하기 위해 cmake를 다시 실행하지 않고는 동일한 시스템에서 소스 디렉토리를 이동할 수도 없습니다! 따라서 선택은 cmake와 make 중 하나가 아니라 휴대용 Makefile을 직접 작성하거나 cmake를 사용하여 각 빌드 시스템에서 이식 할 수없는 파일을 생성하는 것입니다 (Windows에서 Cygwin 또는 mingw를 사용할 수 있다는 점을 감안할 때 일반적으로 전자가 더 쉽다는 것을 알 수 있습니다. )
Ernest Friedman-Hill

1
좋은 질문이지만 구체적인 대답은 없습니다. 두 도구 모두 다른 문제를 해결하려고하기 때문입니다. cmake는 프로그램을 빌드하는 방법에 대한 정보를 사용하여 프로그램을 빌드하는 메이크 파일을 생성합니다. 따라서 cmake는 추상 빌드 규칙이있는 언어이고 gnu make는 방향성 비순환 그래프 순회에서 프로그램을 실행하는 종속성 해결입니다.
Alex

답변:


118

다음 Makefile은 prog소스에서 이름이 지정된 실행 파일을 빌드 합니다 prog1.c, prog2.c, prog3.c and main.c. prog에 연결되어 libmystatlib.alibmydynlib.so모두 또한 소스에서 내장되어있다. 또한, prog라이브러리 사용 libstuff.astuff/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.txtMakefile의 유사점에 밑줄을 긋는 몇 가지 주석과 함께 (거의) 똑같은 작업을 수행합니다.

#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속성을 통해 ) 및 기타 여러 플랫폼의 독립적 인 포함을 제공합니다 . 그래도 더 모호한 설정은 Makefile뿐만 아니라 CMake에서도 직접 구현할 수 있습니다 ( COMPILE_FLAGS 및 유사한 속성 사용). 물론 CMake는 타사 라이브러리 (예 : OpenGL)가 이식 가능한 방식으로 포함될 때 실제로 빛을 발합니다.

  • Makefile을 사용하는 경우 빌드 프로세스에는 make명령 줄에 입력하는 한 단계가 있습니다 . CMake의 경우 두 단계가 있습니다. 먼저 빌드 환경을 설정해야합니다 ( cmake <source_dir>빌드 디렉토리 에 입력 하거나 일부 GUI 클라이언트를 실행하여). 이렇게하면 선택한 빌드 시스템에 따라 Makefile 또는 이와 동등한 것이 생성됩니다 (예 : Unixes의 경우 make, Windows의 경우 VC ++ 또는 MinGW + Msys). 빌드 시스템은 매개 변수로 CMake에 전달할 수 있습니다. 그러나 CMake는 시스템 구성에 따라 합리적인 기본 선택을합니다. 둘째, 선택한 빌드 시스템에서 실제 빌드를 수행합니다.

소스 및 빌드 지침은 https://github.com/rhoelzel/make_cmake 에서 사용할 수 있습니다 .


3
Makefile이 지나치게 복잡하지 않습니까? 사용하여 CPPFLAGS대신 INCDIR하나의 규칙에 내장 컴파일러의 명시적인 호출이 있었던 것이다 중복 사용했습니다 수 있습니다. ar 처리와 마찬가지로 기본 제공 규칙도이를 다룰 수 있습니다. 또한, 왜 설정 CPPCC명시 적으로? 이미에 의해 좋은 값으로 설정되어 make있으며 미리 정의 된 변수입니다. make또한 어떤 종류의 소스에 어떤 컴파일러를 사용할지 인식합니다. 내장 된 규칙은 많습니다.
Christian Hujer 2015

1
그리고 이러한 변수의 대부분 :==.
Christian Hujer 2015

1
설명을 보면 cmake더 비슷 automake이상 make.
ivan_pozdeev

제공된 Makefile은 3/4 줄로 줄일 수 있습니다. INCLUDES대신 지정해야 합니다 INCDIR. % .o : %. c 규칙은 필요하지 않습니다.
shuva

6

빌드 시스템으로 CMake를 사용하는 일부 소프트웨어를 가져옵니다 (예로 선택할 수있는 많은 오픈 소스 프로젝트가 있습니다). 소스 코드를 가져 와서 CMake를 사용하여 구성합니다. 결과 메이크 파일을 읽고 즐기십시오.

이러한 도구는 일대일로 매핑되지 않는다는 점을 명심해야합니다. 가장 분명한 차이점은 CMake는 서로 다른 파일 (예 : C 헤더 및 소스 파일) 간의 종속성을 스캔하는 반면 make는이를 makefile 작성자에게 맡긴다는 것입니다.


4

이 질문이 파일 의 샘플 Makefile출력에 관한 것이라면 CMakeList.txtcmake-backend 소스를 확인하고 그러한 Makefile. @Roberto의 회신에 추가하지 않으면 세부 정보를 숨기고 간단하게 만들려고합니다.

CMake 함수

Make규칙 및 레시피를위한 유연한 도구 이지만 CMake구성 기능도 추가하는 추상화 계층입니다.

내 평야 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 기능) Vs Make 규칙

에서 대신 사용된다 . 유사 기능 외에도 체인을 제공하십시오. 내 미니멀리즘 은 다음과 같이 보일 것입니다.Makefilerules and recipesfunctionsfunctionrules and recipesMakefile

-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

여기 에서이 스 니펫을 가져와 수정했습니다. 일부 암시 적 규칙이이 파일에 추가되며 이는 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에 포함 및 라이브러리 경로 추가

cmake함수 를 사용하여 할 수 있습니다 .

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

Make에 포함 및 라이브러리 경로 추가 대

다음과 같은 줄을 추가하여 포함 및 라이브러리를 추가 할 수 있습니다.

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

위의 행은 자동 생성 도구 또는 pkg-config에서 생성 할 수 있습니다. (Makefile은 자동 구성 도구에 종속되지 않음)

CMake 구성 / tweek

일반적으로 기능 을 사용하여 도구 config.h처럼 일부 파일 을 생성 할 수 있습니다. 사용자 정의 함수를 작성하는 더 많은 트릭을 수행 할 수 있습니다. 마지막으로 다음과 같은 구성을 선택할 수 있습니다.auto-configconfigure_file

cmake --build . --config "Release"

option기능을 사용하여 몇 가지 구성 가능한 옵션을 추가 할 수 있습니다 .

Makefile 구성 / 조정

어떤 식 으로든 디버그 플래그로 컴파일해야한다면 다음 make과 같이 호출 할 수 있습니다 .

make CXXFLAGS=NDEBUG

나는 내부 변수를 생각 Makefile-rules하고 CMake-functions더 파고와 비교, 행운을 위해 좋은 시작이다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.