Cmake mi yoksa örnek kodlar mı oluşturun?


118

Her ikisinin de aynı şeyi yaptığı Makefiles ( make) ve CMakeLists.txt( cmake) için herhangi bir örnek kod olup olmadığını merak ediyordum (tek fark birinin içine makeve diğerinin yazılmasıdır cmake).

'Cmake vs make' aramaya çalıştım ama hiçbir zaman herhangi bir kod karşılaştırması bulamadım. Basit bir durum için bile olsa farklılıkları anlamak gerçekten yardımcı olacaktır.


20
+1 Bu iyi bir sorudur; başladığımda bunu da cmakeistedim. Ama bulacağınızdan şüpheliyim çünkü yetenekler birbiriyle o kadar iyi eşleşmiyor. Öyle cmakedavranmaya çalışırsanız make, kendinizi ciddiye alırsınız. Sıfırdan başlamak için en iyisi. Önemsiz olan makeşeyler oldukça ilgilidir cmakeve bunun tersi de geçerlidir.
Ernest Friedman-Hill

1
@ ErnestFriedman-Hill, bununla ilgili daha fazla ayrıntı var mı? Öyleyse makeve cmakerakip araçlar yerine tamamlayıcı olarak görülmeleri gerekecek kadar farklı mı?
Ehtesh Choudhury

2
@Shurane - cmake kendi başına bir şey inşa etmez; Makefile'lar (ve diğer benzer yapı betikleri) oluşturur ve bunları çalıştırırsınız. Bu nedenle, cmake dosyalarını yazarken, bir komutun oluşturma sırasında mı yoksa derleme sırasında mı uygulanacağını düşünmeniz gerekir. Örneğin, derleme sırasında joker karakterli bir dosya kümesini kopyalamak gibi bazı eylemler, cp *.x $(OUTDIR)Makefile'da yazacağınız " " eylemlere kıyasla oldukça karmaşıktır . Belki benim için en can sıkıcı kısmı üretilen Makefile'lar tasarımdan tamamen nonportable ve esnek olmayan (devam) olmasıdır
Ernest Friedman-Tepesi

1
(devam) Makefile'ı yeniden oluşturmak için cmake'ı yeniden çalıştırmadan kaynak dizini aynı makinede taşıyamazsınız! Yani seçim cmake ve make arasında değil, taşınabilir Makefile'ları kendiniz yazmak veya her derleme makinesinde taşınabilir olmayanlar oluşturmak için cmake kullanmak arasında (ve Windows'ta Cygwin veya mingw kullanabileceğiniz düşünüldüğünde, genellikle ilkini daha kolay buluyorum. )
Ernest Friedman-Hill

1
güzel bir soru, ancak belirli bir cevap yok, çünkü her iki araç da farklı bir sorunu çözmeye çalışıyor. cmake, programların nasıl oluşturulacağı hakkında bilgi alır, programı oluşturan makefile dosyaları oluşturur. Bu nedenle cmake, soyut oluşturma kurallarına sahip bir dildir ve gnu make, programları yönlendirilmiş döngüsel olmayan bir grafik geçişinde çalıştıran bir bağımlılık çözümüdür.
Alex

Yanıtlar:


118

Aşağıdaki Makefile prog, kaynaklardan adlandırılmış bir yürütülebilir dosya oluşturur prog1.c, prog2.c, prog3.c and main.c. progbirbirine bağlıdır libmystatlib.a ve libmydynlib.soher ikisi de kaynaktan oluşturulmuştur. Ayrıca, progkütüphane kullanır libstuff.aiçinde stuff/libve onun başlığını stuff/include. Makefile varsayılan olarak bir yayın hedefi oluşturur, ancak ayrıca bir hata ayıklama hedefi sunar:

#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 ile benzerliklerin altını çizmek için bazı yorumlarla (neredeyse) tamamen aynı olan bir şudur:

#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")

Bu basit örnekte en önemli farklar şunlardır:

  • CMake, hangi tür kaynak için hangi derleyicilerin kullanılacağını tanır. Ayrıca, her hedef türü için doğru komut dizisini çağırır. Bu nedenle, gibi komutların hiçbir açık olduğu belirtilen $(CC) ..., $(RANLIB) ...vb.

  • Başlık dosyalarının, kitaplıkların vb. Dahil edilmesiyle ilgili tüm olağan derleyici / bağlayıcı bayrakları, platformdan bağımsız / sistemden bağımsız komutlarla değiştirilir.

  • Ayıklama bayraklar ya değişkeni ayarlayarak dahildir CMAKE_BUILD_TYPE"Debug", ya da programın çağrılırken CMake bunu ileterek: cmake -DCMAKE_BUILD_TYPE:STRING=Debug.

  • CMake ayrıca '-fPIC' bayrağının ( POSITION_INDEPENDENT_CODEmülk aracılığıyla ) ve daha pek çoğunun platformdan bağımsız eklenmesini sunar . Yine de, CMake'de ve bir Makefile'da ( COMPILE_FLAGS ve benzer özellikler kullanılarak) daha belirsiz ayarlar elle uygulanabilir . Elbette CMake, üçüncü taraf kitaplıkları (OpenGL gibi) taşınabilir bir şekilde dahil edildiğinde gerçekten parlamaya başlar.

  • Bir Makefile kullanıyorsanız, yani makekomut satırına yazarak derleme işleminin bir adımı vardır . CMake için iki adım vardır: İlk olarak, derleme ortamınızı kurmanız gerekir ( cmake <source_dir>yapı dizininize yazarak veya bazı GUI istemcileri çalıştırarak). Bu, seçtiğiniz derleme sistemine bağlı olarak bir Makefile veya eşdeğer bir şey oluşturur (ör. Windows'ta Unixes veya VC ++ veya MinGW + Msys üzerinde make). Derleme sistemi bir parametre olarak CMake'ye geçirilebilir; ancak CMake, sistem yapılandırmanıza bağlı olarak makul varsayılan seçimler yapar. İkinci olarak, seçilen derleme sisteminde asıl derlemeyi gerçekleştirirsiniz.

Kaynaklar ve yapım talimatları https://github.com/rhoelzel/make_cmake adresinde mevcuttur .


3
Makefile aşırı karmaşık değil mi? Yerleşik kurallar CPPFLAGSyerine INCDIRbirini kullanarak , derleyicinin açık çağrısı gereksiz olabilirdi. Benzer şekilde ar'ın işlenmesi için de yerleşik kurallar bunu da kapsayabilir. Ayrıca, neden sabit CPPve CCaçıkça? Zaten iyi değerlere ayarlanmışlar make, önceden tanımlanmış değişkenlerdir. makeayrıca hangi derleyicinin hangi tür kaynak için kullanılacağını tanır, yerleşik kurallar çoktur.
Christian Hujer

1
Ve bu değişkenlerin çoğu :=yerine atanmalıdır =.
Christian Hujer

1
Açıklaması baktığımızda, cmakedaha karşılaştırılabilir automakedaha make.
ivan_pozdeev

Sağlanan Makefile, 3/4 satıra indirgenebilir. Bunun INCLUDESyerine belirtmeniz GEREKİR INCDIR. % .O:%. C kurallarına ihtiyacınız yok.
shuva

6

CMake'i derleme sistemi olarak kullanan bazı yazılımları alın (örnek olarak seçebileceğiniz çok sayıda açık kaynaklı proje var). Kaynak kodunu alın ve CMake kullanarak yapılandırın. Ortaya çıkan makefiles'ı okuyun ve keyfini çıkarın.

Unutulmaması gereken bir şey, bu araçların bire bir eşleştirmediğini. En belirgin fark, CMake'in farklı dosyalar (örneğin C başlığı ve kaynak dosyaları) arasındaki bağımlılıkları tararken make bunu makefile yazarlarına bırakmasıdır.


4

Bu soru dosyanın örnek bir Makefileçıktısıyla CMakeList.txtilgiliyse, lütfen cmake-backend kaynaklarını kontrol edin ve böyle bir tane oluşturun Makefile. @Roberto'nun cevabına eklenmiyorsa, detayları gizleyerek basitleştirmeye çalışıyorum.

CMake işlevi

MakeKurallar ve tarif için esnek bir araç olsa CMakeda, yapılandırma özelliğini de ekleyen bir soyutlama katmanıdır.

Benim ovam şöyle CMakeLists.txtgörünecek,

cmake_minimum_required(VERSION 2.8)
project(example)
file(GLOB testapp_SOURCES *.cc)
add_executable(testapp ${testapp_SOURCES})

CMakeYapının howyapılabileceğini gizleyen unutmayın . whatGirdi ve çıktıyı sadece belirtmiştik .

CMakeLists.txtTarafından tanımlanan fonksiyon aramalar listesini içerir cmake.

(CMake işlevi) Vs Kural koy

Gelen yerine kullanılmaktadır . Benzeri özelliğe ek olarak , zincirleme sağlayın. Minimalistim aşağıdaki gibi görünecek,Makefilerules and recipesfunctionsfunctionrules and recipesMakefile

-include "executable.mk"
TARGETS=testapp.bin
all:${TARGETS}

executable.mkAşağıdaki gibi görünecek olsa da ,

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)

Ben ile başlamak zorundadır sıfırdan başlayarak Makefileaşağıdaki gibi,

all: testapp.bin

testapp.bin:sourcea.o sourcb.o
    $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LIBS)

.PHONY: all clean

clean:
    $(RM) $(OBJECTS) testapp.bin

Bu pasajı buradan aldım ve değiştirdim. Makefile belgelerinde bulunabilecek bazı örtük kuralların bu dosyaya eklendiğine dikkat edin. Bazı örtük değişkenler de burada önemlidir.

Yapının yapılabileceğini gösteren Makefileayrıntıları sağlayan unutmayın . Tanımlanan detayları tek bir dosyada tutmak için yazmak mümkündür . Bu şekilde makefile, daha önce gösterdiğim gibi azaltılabilir.recipehowexecutable.mk

İç Değişkenler CMakeveMake

Şimdi biraz ilerledikçe, CMakeaşağıdaki gibi bir derleyici bayrağı ayarlayabiliriz,

set(CMAKE_C_FLAGS "-Wall")

Lütfen dosyadaki CMakevarsayılan değişkenler hakkında daha fazla bilgi edinin CMakeCache.txt. CMakeYukarıdaki kod eşit olacaktır Make, aşağıdaki kod

CFLAGS = -Wall

Aynı şekilde CFLAGSdahili bir değişken olduğuna dikkat Makeedin,CMAKE_C_FLAGS iç değişkendirCMake .

CMake'de dahil etme ve kitaplık yolu ekleme

Bunu cmakefonksiyonları kullanarak yapabiliriz .

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

Make'e dahil etme ve kitaplık yolu ekleme Vs

Aşağıdakiler gibi satırlar ekleyerek include ve libraries ekleyebiliriz,

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

Yukarıdaki bu satırların auto-gen araçlarından veya pkg-config'den oluşturulabileceğini unutmayın. (Makefile otomatik yapılandırma araçlarına bağımlı olmasa da)

CMake yapılandır / tweek

Normalde, işlev kullanarak araçlar config.hgibi bazı dosyalar oluşturmak mümkündür . Özel işlevler yazarken daha fazla hile yapmak mümkündür. Ve son olarak aşağıdaki gibi bir yapılandırma seçebiliriz,auto-configconfigure_file

cmake --build . --config "Release"

optionFonksiyonu kullanarak bazı yapılandırılabilir seçenekler eklemek mümkündür .

Makefile yapılandır / ince ayar

Bir şekilde onu bir hata ayıklama bayrağıyla derlememiz gerekirse, makebenzerini çağırabiliriz ,

make CXXFLAGS=NDEBUG

Bence iç değişkenler Makefile-rulesve CMake-functionskarşılaştırma için iyi bir başlangıç, daha fazla kazmada iyi şanslar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.