Cmake против создания образцов кодов?

Мне было интересно, есть ли какой-нибудь пример кода для Makefileс (make) а также CMakeLists.txt (cmake) что оба делают одно и то же (единственное отличие состоит в том, что один написан на make а другой в cmake).

Я пытался найти 'cmake vs make', но я не нашел ни одного сравнения кода. Было бы действительно полезно понять различия, даже если бы только для простого случая.

3 ответа

Следующий 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 или что-то эквивалентное, в зависимости от выбранной вами системы сборки (например, make на Unixes или VC++ или MinGW + Msys на Windows). Система сборки может быть передана в CMake в качестве параметра; тем не менее, CMake делает разумный выбор по умолчанию в зависимости от конфигурации вашей системы. Во-вторых, вы выполняете фактическую сборку в выбранной системе сборки.

Исходники и инструкции по сборке доступны по адресу https://github.com/rhoelzel/make_cmake.

Возьмите какое-нибудь программное обеспечение, которое использует CMake в качестве своей системы сборки (в качестве примера можно выбрать множество проектов с открытым исходным кодом). Получить исходный код и настроить его с помощью CMake. Читайте получившиеся make-файлы и наслаждайтесь.

Следует иметь в виду, что эти инструменты не отображаются один на один. Наиболее очевидное отличие заключается в том, что CMake сканирует зависимости между различными файлами (например, заголовок C и исходные файлы), тогда как make оставляет это авторам make-файлов.

Если этот вопрос о образце Makefile выход из CMakeList.txt затем проверьте исходники cmake-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) против создания правил

В 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

Я получил этот фрагмент отсюда и изменил его. Обратите внимание, что в этот файл добавлены некоторые неявные правила, которые можно найти в документации makefile. Некоторые неявные переменные также актуальны здесь.

Обратите внимание, что Makefile предоставляет детали recipe показ how сборка может быть сделана. Можно написать executable.mk сохранить детали, определенные в одном файле. Таким образом, make-файл может быть уменьшен, как я показал ранее.

Внутренние переменные в CMake а также Make

Сейчас немного продвинулись, в CMake мы можем установить флаг компилятора следующим образом:

set(CMAKE_C_FLAGS "-Wall")

Пожалуйста, узнайте больше о CMake переменные по умолчанию в CMakeCache.txt файл. CMake код выше будет эквивалентен Make код ниже,

CFLAGS = -Wall

Обратите внимание, что CFLAGS является внутренней переменной в Make, так же, CMAKE_C_FLAGS является внутренней переменной в CMake,

добавление include и путь к библиотеке в CMake

Мы можем сделать это в cmake используя функции.

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

Против добавления include и пути к библиотеке в Make

Мы можем добавить include и библиотеки, добавив строки, подобные следующим,

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

Обратите внимание, что приведенные выше строки могут быть сгенерированы из инструментов auto-gen или pkg-config. (хотя Makefile не зависит от инструментов автоконфигурации)

CMake настроить / твик

Обычно можно генерировать некоторые config.h файл так же, как auto-config инструменты с помощью configure_file функция. Можно сделать больше трюков при написании пользовательских функций. И, наконец, мы можем выбрать конфигурацию, как показано ниже,

cmake --build . --config "Release"

Можно добавить некоторые настраиваемые параметры, используя option функция.

Makefile настроить / настроить

Если каким-то образом нам нужно скомпилировать его с некоторым отладочным флагом, мы можем вызвать make лайк,

make CXXFLAGS=NDEBUG

Я думаю, что внутренние переменные, Makefile-rules а также CMake-functions Хорошее начало для сравнения, удачи в копании.

Другие вопросы по тегам