C ++, «старомодный» способ - PullRequest
9 голосов
/ 18 января 2010

Я изучал C ++ в школе, чтобы создавать небольшие программы для командной строки.

Однако я создавал свои проекты только с IDE, включая VS08 и QtCreator.

Я понимаю процесс создания проекта: скомпилировать исходный код в объектный код, а затем связать их с исполняемым файлом, специфичным для платформы (.exe, .app и т. Д.). Я также знаю, что большинство проектов также используют make для упрощения процесса компиляции и компоновки нескольких исходных файлов и файлов заголовков.

Дело в том, что хотя IDE делают все это под капотом, делая жизнь очень легкой, я не очень знаю , что на самом деле происходит, и чувствую, что мне нужно привыкнуть к созданию проектов «по старинке»: из командной строки, явно используя цепочку инструментов.

Я знаю, что такое Makefile s, но не знаю, как их написать.
Я знаю, что делает gcc, но не знаю, как это использовать.
Я знаю, что делает компоновщик, но не знаю, как его использовать.

То, что я ищу, это либо объяснение, либо ссылка на учебное пособие, которое объясняет рабочий процесс для проекта C ++, от первой записи кода до запуска созданного исполняемого файла.

Мне бы очень хотелось узнать, что, как и почему строит C ++.

(Если это имеет какое-то значение, я использую Mac OS X с gcc 4.0.1 и создаю 3.81)

Спасибо!

Ответы [ 8 ]

15 голосов
/ 18 января 2010

1001 * Компиляция * Допустим, вы хотите написать простое приложение "Hello World". У вас есть 3 файла, hello.cpp hello-writer.cpp и hello-writer.h, содержимое которых равно // hello-writer.h void WriteHello(void); // hello-writer.cpp #include "hello-writer.h" #include <stdio> void WriteHello(void){ std::cout<<"Hello World"<<std::endl; } // hello.cpp #include "hello-writer.h" int main(int argc, char ** argv){ WriteHello(); } Файлы * .cpp преобразуются в объектные файлы с помощью g++ с помощью команд g++ -c hello.cpp -o hello.o g++ -c hello-writer.cpp -o hello-writer.o Флаг -c на данный момент пропускает связывание. Чтобы связать все модули вместе, необходимо запустить g++ hello.o hello-writer.o -o hello создание программы hello. Если вам нужно связать какие-либо внешние библиотеки, вы добавляете их в эту строку, например, -lm для математической библиотеки. Фактические файлы библиотеки будут выглядеть примерно так: libm.a или libm.so, при добавлении флага компоновщика вы игнорируете суффикс и часть имени файла 'lib'. Makefile

Для автоматизации процесса сборки вы используете make-файл, который состоит из ряда правил, перечисляющих объект для создания и файлы, необходимые для его создания. Например, hello.o зависит от hello.cpp и hello-writer.h, его правило

hello.o:hello.cpp hello-writer.h
     g++ -c hello.cpp -o hello.o # This line must begin with a tab.

Если вы хотите прочитать руководство по сборке, в нем рассказывается, как использовать переменные и автоматические правила для упрощения вещей. Вы должны быть в состоянии просто написать

hello.o:hello.cpp hello-writer.h

и правило будет создано автоматически. Полный make-файл для примера hello:

all:hello
hello:hello.o hello-writer.o
    g++ hello.o hello-writer.o -o hello
hello.o:hello.cpp hello-writer.h
    g++ -c hello.cpp -o hello.o
hello-writer.o:hello-writer.cpp hello-writer.h
    g++ -c hello-writer.cpp -o hello-writer.o

Помните, что строки с отступом должны начинаться с вкладок. Не то чтобы не всем правилам нужен фактический файл, цель all просто говорит создать hello. Обычно это первое правило в make-файле, первое создается автоматически при запуске make.

После всех этих настроек вы сможете перейти в командную строку и запустить

$ make
$ ./hello
Hello World

Более продвинутый материал Makefile

Есть также несколько полезных переменных, которые вы можете определить в вашем make-файле, включая

  • CXX: c ++ компилятор
  • CXXFLAGS: Дополнительные флаги для передачи компилятор (например, включают в себя каталоги с -I)
  • LDFLAGS: дополнительные флаги для перейти на компоновщик
  • LDLIBS: библиотеки по ссылке
  • CC: c компилятор (также используется для ссылка)
  • CPPFLAGS: флаги препроцессора

Определить переменные с помощью =, добавить к переменным с помощью +=.

Правило по умолчанию для преобразования файла .cpp в файл .o:

$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@

, где $< - первая зависимость, а $@ - выходной файл. Переменные расширяются, заключая их в $(), это правило будет выполняться с шаблоном hello.o:hello.cpp

Аналогично, правило компоновщика по умолчанию -

$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)

, где $^ - все предпосылки. Это правило будет выполняться с шаблоном hello:hello.o hello-writer.o. Обратите внимание, что здесь используется компилятор c, если вы не хотите переопределять это правило и используете c ++, добавьте библиотеку -lstdc++ в LDLIBS со строкой

LDLIBS+=-lstdc++

в make-файле.

Наконец, если вы не перечислите зависимости файла .o, make может найти их сам, поэтому минимальный make-файл может быть

LDFLAGS=-lstdc++
all:hello
hello:hello.o hello-writer.o

Обратите внимание, что при этом игнорируется зависимость двух файлов от hello-writer.h, поэтому, если заголовок будет изменен, программа не будет перестроена. Если вам интересно, проверьте флаг -MD в документации gcc, чтобы узнать, как автоматически генерировать эту зависимость.

Окончательный make-файл

Разумный финальный make-файл будет

// Makefile
CC=gcc
CXX=g++
CXXFLAGS+=-Wall -Wextra -Werror
CXXFLAGS+=-Ipath/to/headers
LDLIBS+=-lstdc++ # You could instead use CC = $(CXX) for the same effect 
                 # (watch out for c code though!)

all:hello                                   # default target
hello:hello.o hello-world.o                 # linker
hello.o:hello.cpp hello-world.h             # compile a module
hello-world.o:hello-world.cpp hello-world.h # compile another module
    $(CXX) $(CXXFLAGS) -c $< -o $@          # command to run (same as the default rule)
                                            # expands to g++ -Wall ... -c hello-world.cpp -o hello-world.o
10 голосов
/ 18 января 2010

Простой пример часто полезен для демонстрации основной процедуры, поэтому:

Пример использования gcc для компиляции файлов C ++:

$ g++ -c file1.cpp                 # compile object files
[...]
$ g++ -c file2.cpp
[...]
$ g++ -o program file1.o file2.o   # link program
[...]
$ ./program                        # run program

Чтобы использовать make для этой сборки, можно использовать следующий Makefile:

# main target, with dependencies, followed by build command (indented with <tab>)
program: file1.o file2.o
    g++ -o program file1.o file2.o

# rules for object files, with dependencies and build commands
file1.o: file1.cpp file1.h
    g++ -c file1.cpp

file2.o: file2.cpp file2.h file1.h
    g++ -c file2.cpp

Пример использования Makefile:

$ make                              # build it
[...]
$ ./program                         # run it

Подробную информацию вы можете найти в руководстве пользователя Gnu и в документации GCC .

4 голосов
/ 18 января 2010

Я знаю, что такое Make-файлы, но не знаю, как их написать.

Синтаксис make ужасен, но GNU make docs неплох. Основной синтаксис:

<target> : <dependency> <dependency> <dep...>
<tab>    <command>
<tab>    <command>

Определяет команды для построения цели из заданных зависимостей.

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

Вам также следует попробовать создать простую марку (уберите кучу сложных функций для вашей первой версии); Я думаю, что это один из случаев, когда это поможет вам лучше понять ситуацию.

Я знаю, что делает gcc, но не знаю, как его использовать.

Опять же, man g++, информационные страницы и другая документация полезны, но основное использование при непосредственном вызове (а не через систему сборки) будет:

g++ file.cpp -o name            # to compile and link
g++ file.cpp other.cpp -o name  # to compile multiple files and link as "name"

Вы также можете написать свой собственный скрипт оболочки (ниже мой ~ / bin / c ++ упрощенный), чтобы включить $ CXXFLAGS, чтобы вы не забыли:

#!/bin/sh
g++ $CXXFLAGS "$@"

Вы также можете включить любую другую опцию. Теперь вы можете установить эту переменную окружения ($ CXXFLAGS, стандартная переменная для флагов C ++) в вашем .bashrc или аналогичном или переопределить его в конкретном сеансе для работы без make-файла (который тоже хорошо работает с make).

Также используйте флаг -v, чтобы увидеть подробности о том, что делает g ++, включая ...

Я знаю, что делает компоновщик, но не знаю, как его использовать.

Линкер - это то, что берет объектные файлы и связывает их, как я уверен, вы знаете, но g++ -v покажет вам точную команду, которую он использует. Сравните gcc -v file.cpp (gcc может работать с файлами C ++) и g++ -v file.cpp, чтобы увидеть разницу в командах компоновщика, которая часто приводит к сбою первой, например. Make также показывает команды, так как запускает их по умолчанию.

Лучше не использовать компоновщик напрямую, потому что гораздо проще использовать gcc или g ++ и назначать им конкретные опции компоновщика, если это необходимо.

2 голосов
/ 18 января 2010

Просто, чтобы бросить это, полную документацию по gcc можно найти здесь: http://www.delorie.com/gnu/docs/gcc/gcc_toc.html

0 голосов
/ 22 марта 2010

Это то, что помогло мне изучить autoconf, automake, ...:

http://www.bioinf.uni -freiburg.de / ~ mmann / HowTo / automake.html

Это хороший учебник, переходящий от простого мира приветствия к более сложным структурам с библиотеками и т. Д.

0 голосов
/ 18 января 2010

Мне нравится это причудливое введение в создание программы hello world с gcc на основе Linux, но командная строка должна отлично работать на OS / X. В частности, он проведет вас через некоторые распространенные ошибки и увидит сообщения об ошибках.

Святые компиляторы, Робин, проклятая штука сработала!

0 голосов
/ 18 января 2010

Вы также можете заглянуть в Autoproject, который настраивает файлы automake и autoconf, что упрощает компиляцию ваших пакетов на разных платформах: http://packages.debian.org/unstable/devel/autoproject

0 голосов
/ 18 января 2010

компилятор принимает cpp и превращается в объектный файл, который содержит собственный код и некоторую информацию об этом собственном коде

компоновщик берет объектные файлы и выдает исполняемый файл, используя дополнительную информацию в объектном файле .... он находит все ссылки на одни и те же вещи и связывает их, а также делает изображение и полезное для операционной системы. знать, как загрузить весь код в память.

проверить форматы объектных файлов, чтобы лучше понять, что производит компилятор

http://en.wikipedia.org/wiki/Object_file (разные компиляторы используют разные форматы)

также проверить (для GCC)

http://pages.cs.wisc.edu/~beechung/ref/gcc-intro.html на том, что вы вводите в командной строке

...