Сборка проекта на С++ в GNU/Linux
Язык С++ является компилируемым, то есть трансляция кода с языка высокого уровня на инструкции машинного кода происходит не в момент выполнения, а заранее — в процессе изготовления так называемого исполняемого файла (в ОС Windows такие файлы имеют расширение .exe , а в ОС GNU/Linux чаще всего не имеют расширения).
hello.cpp
Пример простой программы на С++, которая печатает «Привет, Мир!»:
#include int main() std::cout <"Hello, World!" <std::endl; return 0; >
Для вывода здесь используется стандартная библиотека iostream , поток вывода std::cout .
Исполняемые операторы в программах на С++ не могут быть сами по себе — они должны быть обязательно заключены в функции.
Функция main() — это главная функция, выполнение программы начинается с её вызова и заканчивается выходом из неё. Возвращаемое значение main() в случае успешных вычислений должно быть равно 0, что значит «ошибка номер ноль», то есть «нет ошибки». В противном процесс, вызвавший программу, может посчитать её выполнившейся с ошибкой.
Чтобы выполнить программу, нужно её сохранить в текстовом файле hello.cpp и скомпилировать следующей командой:
$ g++ -o hello hello.cpp
Опция -o сообщает компилятору, что итоговый исполняемый файл должен называться hello . g++ — это компилятор языка C++, входящий в состав проекта GCC (GNU Compiler Collection). g++ не является единственным компиляторм языка C++. Помимо него в ходе курса мы будет использовать компилятор clang , поскольку он обладает рядом преимуществ, из которых нас больше всего интересует одно — этот компилятор выдаёт более понятные сообщения об ошибках по сравнению с g++ .
Упражнение №1
Скомпилируйте и выполните данную программу.
Ввод и вывод на языке С++
В Python и в С ввод и вывод синтаксически оформлены как вызов функции, а в С++ — это операция над объектом специального типа — потоком.
Потоки определяются в библиотеке iostream, где определены операции ввода и вывода для каждого встроенного типа.
Вывод
Все идентификаторы стандартной библиотеки определены в пространстве имен std , что означает необходимость обращения к ним через квалификатор std:: .
std::cout "mipt"; std::cout 2018; std::cout '.'; std::cout true; std::cout std::endl;
Заметим, что в С++ мы не прописываем типы выводимых значений, компилятор неким (пока непонятным) способом разбирается в типе выводимого значения и выводит его соответствующим образом.
Вывод в один и тот же поток можно писать в одну строчку:
std::cout "mipt" 2018 '.' true std::endl;
Для вывода в поток ошибок определён поток std::cerr .
Ввод
Поток ввода с клавиатуры называется std::cin , а считывание из потока производится другой операцией — >> :
std::cin >> x;
Тип считываемого значения определяется автоматически по типу переменной x .
Для всех типов, кроме char , считывание будет производиться с пропуском символов-разделителей и до следующего символа-разделителя. При этом пробел и табуляция так же, как и символ перевода каретки, являются корректными разделителями. Считывание в char происходит посимвольно независимо от типа символа.
Например для введенной строки «Иван Иванович Иванов»,
std::string name; std::cin >> name;
считает в name только первое слово «Иван».
Считать всю строку целиком можно с помощью функции getline() :
std::string name; std::getline(std::cin, name);
Считывать несколько значений можно и в одну строку:
std::cin >> x >> y >> z;
Упражнение №2
Напишите программу, которая считает гипотенузу прямоугольного треугольника по двум катетам. Ввод и вывод стандартные.
| Ввод | Вывод |
| 3 4 | 5 |
Сумма первых n натуральных чисел
Пример программы, которая подсчитывает сумму первых n натуральных чисел:
#include int main() int n = 0; std::cin >> n; int sum = 0; for (int i = 1; i n; i++) sum += i; > std::cout <sum <std::endl; return 0; >
Как известно, если сложную задачу разбить на несколько простых подзадач, то её решение сильно упрощается. Поэтому не стоит писать весь код в одной функции main() . Лучше разбивать код на отдельные функции, каждая из которых решает свою несложную подзадачу, но делает это хорошо. Например, в предыдущем примере можно вынести функциональность подсчёта суммы первых n натуральных чисел в отдельную функцию:
#include int GetNaturalsSum(const int n) int sum = 0; for (int i = 1; i n; i++) sum += i; > return sum; > int main() int n = 0; std::cin >> n; std::cout <GetNaturalsSum(n) <std::endl; return 0; >
Эмперическое правило: каждая функция не должна превышать по размеру 1 экран вашего монитора.
Этапы сборки: препроцессинг, компиляция, компоновка
Компиляция исходных текстов на Си в исполняемый файл происходит в три этапа.
Препроцессинг
Эту операцию осуществляет текстовый препроцессор.
Исходный текст частично обрабатывается — производятся:
- Замена комментариев пустыми строками
- Текстовое включение файлов — #include
- Макроподстановки — #define
- Обработка директив условной компиляции — #if , #ifdef , #elif , #else , #endif
Компиляция
Процесс компиляции состоит из следующих этапов:
- Лексический анализ. Последовательность символов исходного файла преобразуется в последовательность лексем.
- Синтаксический анализ. Последовательность лексем преобразуется в дерево разбора.
- Семантический анализ. Дерево разбора обрабатывается с целью установления его семантики (смысла) — например, привязка идентификаторов к их декларациям, типам, проверка совместимости, определение типов выражений и т. д.
- Оптимизация. Выполняется удаление излишних конструкций и упрощение кода с сохранением его смысла.
- Генерация кода. Из промежуточного представления порождается объектный код.
Результатом компиляции является объектный код.
Объектный код — это программа на языке машинных кодов с частичным сохранением символьной информации, необходимой в процессе сборки.
При отладочной сборке возможно сохранение большого количества символьной информации (идентификаторов переменных, функций, а также типов).
Компоновка
Компоновка также называется связывание или линковка. На этом этапе отдельные объектные файлы проекта соединяются в единый исполняемый файл.
На этом этапе возможны так называемые ошибки связывания: если функция была объявлена, но не определена, ошибка обнаружится только на этом этапе.
Упражнение №3
Выполните в консоли для ранее созданного файла hello.cpp последовательно операции препроцессинга, компиляции и компоновки:
$ g++ -E -o hello1.cpp hello.cpp
- Компиляция:
$ g++ -c -o hello.o hello1.cpp
- Компоновка:
$ g++ -o hello hello.o
Принцип раздельной компиляции
Компиляция — алгоритмически сложный процесс, для больших программных проектов требующий существенного времени и вычислительных возможностей ЭВМ. Благодаря наличию в процессе сборки программы этапа компоновки (связывания) возникает возможность раздельной компиляции.
В модульном подходе программный код разбивается на несколько файлов .cpp , каждый из которых компилируется отдельно от остальных.
Это позволяет значительно уменьшить время перекомпиляции при изменениях, вносимых лишь в небольшое количество исходных файлов. Также это даёт возможность замены отдельных компонентов конечного программного продукта, без необходимости пересборки всего проекта.
Пример модульной программы с раздельной компиляцией на С++
Рассмотрим пример: есть желание вынести часть кода в отдельный файл — пользовательскую библиотеку.
program.cpp
#include "mylib.hpp" const int MAX_DIVISORS_NUMBER = 10000; int main() int number = read_number(); int Divisor[MAX_DIVISORS_NUMBER]; int Divisor_top = 0; factorize(number, Divisor, &Divisor_top); print_array(Divisor, Divisor_top); return 0; >
Подключение пользовательской библиотеки в С++ на самом деле не так просто, как кажется.
Сама библиотека должна состоять из двух файлов: mylib.hpp и mylib.cpp :
mylib.hpp
#ifndef MY_LIBRARY_H_INCLUDED #define MY_LIBRARY_H_INCLUDED #include //считываем число int read_number(); //получаем простые делители числа // сохраняем их в массив, чей адрес нам передан void factorize(int number, int *Divisor, int *Divisor_top); //выводим число void print_number(int number); //распечатывает массив размера A_size в одной строке через TAB void print_array(int A[], size_t A_size); #endif // MY_LIBRARY_H_INCLUDED
mylib.cpp
#include #include "mylib.hpp" //считываем число int read_number() int number; std::cin >> number; return number; > //получаем простые делители числа // сохраняем их в массив, чей адрес нам передан void factorize(int x, int *Divisor, int *Divisor_top) for (int d = 2; d x; d++) while (x%d == 0) Divisor[(*Divisor_top)++] = d; x /= d; > > > //выводим число void print_number(int number) std::cout <number <std::endl; > //распечатывает массив размера A_size в одной строке через TAB void print_array(int A[], size_t A_size) for(int i = A_size-1; i >= 0; i--) std::cout <A[i] <'\t'; > std::cout <std::endl; >
Препроцессор С++, встречая #include «mylib.hpp» , полностью копирует содержимое указанного файла (как текст) вместо вызова директивы. Благодаря этому на этапе компиляции не возникает ошибок типа Unknown identifier при использовании функций из библиотеки.
Файл mylib.cpp компилируется отдельно.
А на этапе компоновки полученный файл mylib.o должен быть включен в исполняемый файл program .
Cреда разработки обычно скрывает весь этот процесс от программиста, но для корректного анализа ошибок сборки важно представлять себе, как это делается.
Упражнение №4
Давайте сделаем это руками:
$ g++ -c mylib.cpp # 1 $ g++ -c program.cpp # 2 $ g++ -o program mylib.o program.o # 3
Теперь, если изменения коснутся только mylib.cpp , то достаточно выполнить только команды 1 и 3. Если только program.cpp, то только команды 2 и 3. И только в случае, когда изменения коснутся интерфейса библиотеки, т.е. заголовочного файла mylib.hpp , придётся перекомпилировать оба объектных файла.
Утилита make и Makefile
Утилита make предназначена для автоматизации преобразования файлов из одной формы в другую. По отметкам времени каждого из имеющихся объектных файлов (при их наличии) она может определить, требуется ли их пересборка.
Правила преобразования задаются в скрипте с именем Makefile , который должен находиться в корне рабочей директории проекта. Сам скрипт состоит из набора правил, которые в свою очередь описываются:
- целями (то, что данное правило делает);
- реквизитами (то, что необходимо для выполнения правила и получения целей);
- командами (выполняющими данные преобразования).
В общем виде синтаксис Makefile можно представить так:
# Отступ (indent) делают только при помощи символов табуляции, # каждой команде должен предшествовать отступ : .
То есть, правило make это ответы на три вопроса:
—> [Как делаем? (команды)] —>
Несложно заметить что процессы трансляции и компиляции очень красиво ложатся на эту схему:
Простейший Makefile
Для компиляции hello.cpp достаточно очень простого мэйкфайла:
hello: hello.cpp gcc -o hello hello.cpp
Данный Makefile состоит из одного правила, которое в свою очередь состоит из цели — hello , реквизита — hello.cpp , и команды — gcc -o hello hello.cpp .
Теперь, для компиляции достаточно дать команду make в рабочем каталоге. По умолчанию make станет выполнять самое первое правило, если цель выполнения не была явно указана при вызове:
Makefile для модульной программы
program: program.o mylib.o g++ -o program program.o mylib.o program.o: program.cpp mylib.hpp g++ -c program.cpp mylib.o: mylib.cpp mylib.hpp g++ -c hylib.cpp
Попробуйте собрать этот проект командой make или make hello . Теперь измените любой из файлов .cpp и соберите проект снова. Обратите внимание на то, что во время повторной компиляции будет транслироваться только измененный файл.
После запуска make попытается сразу получить цель program , но для ее создания необходимы файлы program.o и mylib.o , которых пока еще нет. Поэтому выполнение правила будет отложено и make станет искать правила, описывающие получение недостающих реквизитов. Как только все реквизиты будут получены, make`вернется к выполнению отложенной цели. Отсюда следует, что `make выполняет правила рекурсивно.
Фиктивные цели
На самом деле в качестве make целей могут выступать не только реальные файлы. Все, кому приходилось собирать программы из исходных кодов, должны быть знакомы с двумя стандартными в мире UNIX командами:
$ make $ make install
Командой make производят компиляцию программы, командой make install — установку. Такой подход весьма удобен, поскольку все необходимое для сборки и развертывания приложения в целевой системе включено в один файл (забудем о скрипте configure ). Обратите внимание на то, что в первом случае мы не указываем цель, а во втором целью является вовсе не создание файла install , а процесс установки приложения в систему. Проделывать такие фокусы нам позволяют так называемые фиктивные (phony) цели. Вот краткий список стандартных целей:
all — является стандартной целью по умолчанию. При вызове make ее можно явно не указывать; clean — очистить каталог от всех файлов полученных в результате компиляции; install — произвести инсталляцию; uninstall — и деинсталляцию соответственно.
Для того чтобы make не искал файлы с такими именами, их следует определить в Makefile , при помощи директивы .PHONY . Далее показан пример Makefile с целями all , clean , install и uninstall :
.PHONY: all clean install uninstall all: program clean: rm -rf mylib *.o program.o: program.cpp mylib.hpp gcc -c -o program.o program.cpp mylib.o: mylib.cpp mylib.hpp gcc -c -o mylib.o mylib.cpp program: program.o mylib.o gcc -o mylib program.o mylib.o install: install ./program /usr/local/bin uninstall: rm -rf /usr/local/bin/program
Теперь мы можем собрать нашу программу, произвести ее инсталлцию/деинсталляцию, а так же очистить рабочий каталог, используя для этого стандартные make цели.
Обратите внимание на то, что в цели all не указаны команды; все что ей нужно — получить реквизит program . Зная о рекурсивной природе make, не сложно предположить, как будет работать этот скрипт. Также следует обратить особое внимание на то, что если файл program уже имеется (остался после предыдущей компиляции) и его реквизиты не были изменены, то команда make ничего не станет пересобирать. Это классические грабли make. Так, например, изменив заголовочный файл, случайно не включенный в список реквизитов (а надо включать!), можно получить долгие часы головной боли. Поэтому, чтобы гарантированно полностью пересобрать проект, нужно предварительно очистить рабочий каталог:
$ make clean $ make
P.S. Неплохая статья с описанием мейкфайлов.
Сайт построен с использованием Pelican. За основу оформления взята тема от Smashing Magazine. Исходные тексты программ, приведённые на этом сайте, распространяются под лицензией GPLv3, все остальные материалы сайта распространяются под лицензией CC-BY-SA.
Компилятор csc.exe

В действительности необходимость в создании крупных приложений с использованием одного лишь компилятора командной строки C# может никогда не возникнуть, тем не менее, важно понимать в общем, как вручную компилировать файлы кода. Существует несколько причин, по которым освоение этого процесса может оказаться полезным:
- Самой очевидной причиной является отсутствие Visual Studio 2010 или какой-то другой графической IDE-среды.
- Работа может выполняться в университете, где использование инструментов для генерации кода и IDE-сред обычно запрещено.
- Планируется применение автоматизированных средств разработки, таких как msbuild.exe, которые требуют знать опции командной строки для используемых инструментов.
- Возникло желание углубить свои познания в C#. В графических IDE-средах в конечном итоге все заканчивается предоставлением компилятору csc.ехе инструкций относительно того, что следует делать с входными файлами кода C#. В этом отношении изучение происходящего «за кулисами» позволяет получить необходимые знания.
Еще одно преимущество подхода с использованием одного лишь компилятора csc.ехе состоит в том, что он позволяет обрести навыки и чувствовать себя более уверенно при работе с другими инструментами командной строки, входящими в состав .NET Framework 4.0 SDK, так как целый ряд важных утилит работает исключительно в режиме командной строки.
Чтобы посмотреть, как создавать .NET-приложение без IDE-среды, давайте построим с помощью компилятора C# и текстового редактора Notepad простую исполняемую сборку по имени TestApplication.exe. Сначала необходимо подготовить исходный код. Откройте программу Notepad (Блокнот), выбрав в меню Start (Пуск) пункт All Programs — Accessories — Notepad (Все программы — Стандартные — Блокнот), и введите следующее типичное определение класса на C#:
using System; class TestApplication < static void Main() < Console.WriteLine("Привет!"); Console.ReadLine(); >>
После окончания ввода сохраните файл под именем TestApplication.cs. Теперь давайте ознакомимся с ключевыми опциями компилятора C#.
Указание целевых входных и выходных параметров
Первым делом важно разобраться с тем, как указывать имя и тип создаваемой сборки (т.е., например, консольное приложение по имени MyShell.exe, библиотека кода по имени MathLib.dll или приложение Windows Presentation Foundation по имени Halo8.ехе). Каждый из возможных вариантов имеет соответствующий флаг, который нужно передать компилятору csc.ехе в виде параметра командной строки.
Обратите внимание, что параметры, передаваемые компилятору командной строки (а также большинству других утилит командной строки), могут сопровождаться префиксом в виде символа дефиса (-) или слеша (/).
Выходные параметры, которые может принимать компилятор C# приведены в следующей таблице:
| Параметр | Описание |
|---|---|
| /out | Этот параметр применяется для указания имени создаваемой сборки. По умолчанию сборке присваивается то же имя, что у входного файла *.сs |
| /target:exe | Этот параметр позволяет создавать исполняемое консольное приложение. Сборка такого типа генерируется по умолчанию, потому при создании подобного приложения данный параметр можно опускать |
| /target:library | Этот параметр позволяет создавать однофайловую сборку *.dll |
| /target:module | Этот параметр позволяет создавать модуль. Модули являются элементами многофайловых сборок |
| /target:winexe | Хотя приложения с графическим пользовательским интерфейсом можно создавать с применением параметра /target: ехе, параметр /target: winexe позволяет предотвратить открытие окна консоли под остальными окнами |
Чтобы скомпилировать TestApplication.cs в консольное приложение TestApplication.exe, перейдите в каталог, в котором был сохранен файл исходного кода (с помощью флага cd) и введите следующую команду:

Обратите внимание, что здесь C:\myProject — это путь к папке, в которой хранится файл TestApplication.cs. Так же обратите внимание, что здесь флаг /out не был указан явным образом, поэтому исполняемым файл получит имя TestApplication.ехе из-за того, что именем входного файла является TestApplication. Кроме того, для почти всех принимаемых компилятором C# флагов поддерживаются сокращенные версии написания, наподобие /t вместо /target (полный список которых можно увидеть, введя в командной строке команду csc -?).
Теперь можно попробовать запустить приложение TestApplication.ехе из командной строки, введя имя его исполняемого файла:

Добавление ссылок на внешние сборки
Давайте посмотрим, как скомпилировать приложение, в котором используются типы, определенные в отдельной сборке .NET. Если осталось неясным, каким образом компилятору C# удалось понять ссылку на тип System.Console, вспомните, что во время процесса компиляции происходит автоматическое добавление ссылки на mscorlib.dll (если по какой-то необычной причине нужно отключить эту функцию, следует передать компилятору csc.exe параметр /nostdlib).
Модифицируем приложение TestApplication так, чтобы в нем открывалось окно сообщения Windows Forms. Для этого откройте файл TestApplication.cs и измените его следующим образом:
using System; using System.Windows.Forms; class TestApplication < static void Main() < Console.WriteLine("Привет!"); MessageBox.Show("Привет. "); >>
Далее в командной строке нужно проинформировать компилятор csc.exe о том, в какой сборке содержатся используемые пространства имен. Поскольку применялся класс MessageBox из пространства имен System.Windows.Forms, значит, нужно указать компилятору на сборку System.Windows.Forms.dll, что делается с помощью флага /reference (или его сокращенной версии /r):

Если теперь снова попробовать запустить приложение, то помимо консольного вывода в нем должно появиться еще и окно с сообщением:

Кстати, как поступить, когда необходимо указать csc.exe несколько внешних сборок? Для этого нужно просто перечислить все сборки через точку с запятой. В рассматриваемом примере ссылаться на несколько сборок не требуется, но ниже приведена команда, которая иллюстрирует перечисление множества сборок:
csc /r:System.Windows.Forms.dll;System.Drawing.dll *.cs
Компиляция нескольких файлов исходного кода
В текущем примере приложение TestApp.exe создавалось с использованием единственного файла исходного кода * . cs. Хотя определять все типы .NET в одном файле *.cs вполне допустимо, в большинстве случаев проекты формируются из нескольких файлов *.cs для придания кодовой базе большей гибкости. Чтобы стало понятнее, давайте создадим новый класс и сохраним его в отдельном файле по имени HelloMessage.cs:
// Класс HelloMessage using System; using System.Windows.Forms; class HelloMessage < public void Speak() < MessageBox.Show("Привет!!") ; >>
Изменим исходный класс TestApplication так, чтобы в нем использовался класс этого нового типа:
using System; class TestApplication < static void Main() < Console.WriteLine("Привет!"); HelloMessage v = new HelloMessage(); v.Speak(); >>
Чтобы скомпилировать файлы исходного кода на C# , необходимо их явно перечислить как входные файлы:

В качестве альтернативного варианта компилятор C# позволяет использовать групповой символ (*) для включения в текущую сборку всех файлов *.cs, которые содержатся в каталоге проекта:

Вывод, получаемый после запуска этой программы, идентичен предыдущей программе. Единственное отличие между этими двумя приложениями связано с разнесением логики по нескольким файлам.
Работа с ответными файлами в C#
Как не трудно догадаться, для создания сложного приложения C# из командной строки потребовалось бы вводить утомительное количество входных параметров для уведомления компилятора о том, как он должен обрабатывать исходный код. Для облегчения этой задачи в компиляторе C# поддерживается использование так называемых .
В ответных файлах C# размещаются все инструкции, которые должны использоваться в процессе компиляции текущей сборки. По соглашению эти файлы имеют расширение *.rsp (сокращение от response — ответ). Чтобы посмотреть на них в действии, давайте создадим ответный файл по имени TestApplication.rsp, содержащей следующие аргументы (комментарии в данном случае обозначаются символом #):
# Это ответный файл для примера # TestApplication.exe /r:System.Windows.Forms.dll # Параметры вывода и подлежащие компиляции файлы /target:exe /out:TestApplication.ехе *.cs
Теперь при условии сохранения данного файла в том же каталоге, где находятся подлежащие компиляции файлы исходного кода на C#, все приложение можно будет создать следующим образом (обратите внимание на применение символа @):

В случае необходимости допускается также указывать и несколько ответных *.rsp файлов в качестве входных параметров (например, csc @FirstFile.rsp @SecondFile.rsp @ThirdFile.rsp). При таком подходе, однако, следует иметь в виду, что компилятор обрабатывает параметры команд по мере их поступления. Следовательно, аргументы командной строки, содержащиеся в поступающем позже файле *.rsp, могут переопределять параметры из предыдущего ответного файла.
Последним моментом, связанным с ответными файлами, о котором необходимо упомянуть, является то, что с компилятором C# ассоциирован ответный файл csc.rsp, который используется по умолчанию и размещен в том же самом каталоге, что и файл csc.ехе (обычно это С:\Windows\Microsoft. NET\Framework\ , где на месте элемента идет номер конкретной версии платформы). Открыв файл csc.rsp в программе Notepad (Блокнот), можно увидеть, что в нем с помощью флага /r: указано множество сборок .NET, в том числе различные библиотеки для разработки веб-приложений, программирования с использованием технологии LINQ и обеспечения доступа к данным и прочие ключевые библиотеки (помимо, конечно же, самой главной библиотеки mscorlib.dll):

При создании программ на C# с применением csc.ехе ссылка на этот ответный файл добавляется автоматически, даже когда указан специальный файл *.rsp. Из-за наличия такого ответного файла по умолчанию, рассматриваемое приложение TestApplication.ехе можно скомпилировать и c помощью следующей команды (поскольку в csc.rsp уже содержится ссылка на System.Windows.Forms.dll):

Стоит отметить, что в случае добавления с помощью опции /r ссылок на сборки, которые на самом деле не используются, компилятор их проигнорирует. Поэтому беспокоиться по поводу «разбухания кода» не нужно.
Компиляция программы на python 3 в exe с помощью программы cx_Freeze

Наверняка, у каждого Python-программиста возникало непреодолимое желание, а изредка и реальная потребность, скомпилировать свою программу на python в exe файл. Сегодня я расскажу, как это сделать с помощью программы cx_Freeze.
Вопрос 1: а оно надо?
Прежде, чем начинать компилировать программу, нужно убедиться, что это действительно необходимо.
«Компиляция» программы на python — процесс, который может сопровождаться множеством проблем. Более того, это не компиляция в машинный код, как, например, программы на C, а лишь «сборка» в исполняемый файл вашей программы вместе с частью интерпретатора python.
Поэтому, если вы будете использовать программу сами или на компьютерах тех, кто её будет использовать, будет стоять интерпретатор python, то вам не нужно её компилировать.
Установка cx_Freeze
Если компилировать программу на python всё-таки нужно, то скачиваем cx_Freeze с http://www.lfd.uci.edu/~gohlke/pythonlibs/#cx_freeze (так как в ней нет одного неприятного бага, который есть в официальной версии).
Затем устанавливаем, не забывая правильно выбрать директорию, где расположен python.
Компиляция
Компилировать будем программу «блэкджек» (файл 21.py) (кому лень смотреть, привожу полный исходный код).
Создаём в папке с программой файл setup.py с содержимым:
Переходим в командную строку (обычно Пуск → Стандартные → Командная строка). Переходим в папку с программой (в моём случае D:\Dima\py). Запускаем команду C:\Python34\python.exe setup.py build (вместо C:\Python34 нужно написать папку, куда установлен python).
Начнется процесс сборки, в котором cx_Freeze может выдавать предупреждения, но, скорее всего, они не повлияют на работу программы.
Поздравляю! В папке build теперь есть ваша папка с исполняемым файлом!
Заметьте, не файл, а папка! Все остальные файлы также нужны для работы программы (да, это недостаток cx_Freeze). К тому же, при завершении программы окно сразу закрывается (а не ждет нажатия клавиши), поэтому в конец программы нужно дописать что-то вроде:
И скомпилировать ещё раз.
Также можно создать msi-архив командой C:\Python34\python.exe setup.py bdist_msi.
Разумеется, при компиляции более сложных программ вы можете столкнуться с более сложными проблемами.
Для их решения следует воспользоваться официальной документацией.
Для вставки кода на Python в комментарий заключайте его в теги
- Модуль csv - чтение и запись CSV файлов
- Создаём сайт на Django, используя хорошие практики. Часть 1: создаём проект
- Онлайн-обучение Python: сравнение популярных программ
- Книги о Python
- GUI (графический интерфейс пользователя)
- Курсы Python
- Модули
- Новости мира Python
- NumPy
- Обработка данных
- Основы программирования
- Примеры программ
- Типы данных в Python
- Видео
- Python для Web
- Работа для Python-программистов
- Сделай свой вклад в развитие сайта!
- Самоучитель Python
- Карта сайта
- Отзывы на книги по Python
- Реклама на сайте
Компиляция исходного кода#
Первым шагом в процессе сборки является компиляция исходного кода. Результатом этого действия обычно является получение объектного кода – набора инструкций для компьютера, сгенерированных из человекочитаемого исходного кода. Разные компиляторы создают разный объектный код из одного и того же исходного кода и соглашения об именовании у них отличаются.
- Если вы используете определённый компилятор для компиляции одного файла исходного кода программы, то вам необходимо использовать тот же компилятор (или совместимый) для компиляции всех остальных файлов исходного кода этой программы. В конце концов, программа может быть собрана из множества файлов, при это скомпилированные части должны взаимодействовать.
- Каждый файл исходного кода будет скомпилирован и результат будет сохранён в файл с расширением «.o» или «.obj». Именно эти файлы объектного кода являются входными данными для следующего этапа: процесса компоновки.
Компиляторы являются сложными программами: они должны понимать язык программирования гораздо детальнее и глубже, чем средний программист. Кроме того, они должны понимать внутреннюю организацию работы компьютера. В итоге, с годами они были дополнены многочисленными опциями для настройки процесса компиляции и конечной программы, которая будет собрана.
Но основы достаточно просты. Возьмём компилятор gfortran, входящий в состав GNU compiler collection (набор компиляторов GNU). Чтобы скомпилировать простую программу, как приведённая выше, состоящую из одного файла исходного кода, вы выполняете следующую команду, предполагая, что исходный код сохранён в файле «hello.f90»:
$ gfortran -c hello.f90
Выполнение этой команды приведёт к созданию файла «hello.o» (так как компилятор gfortran использует расширение «.o\ в качестве расширения для объектных файлов).
Опция компилятора «-c» означает: только компилировать файлы исходного кода. Если её не указать, то по умолчанию компилятор будет компилировать файлы исходного кода и запускать компоновщик для создания исполняемого файла программы. Выполнение команды:
$ gfortran hello.f90
приведёт к созданию исполняемого файла «a.out» в системах Linux или «a.exe» в системе Windows.
- Компилятор может пожаловаться на содержимое файла исходного кода, если обнаружит в нём что-то неправильное, например, опечатку или неизвестное ключевое слово. В этом случае процесс компиляции прерывается и вы не получите ни объектного файла, ни исполняемого файла программы. Например, если слово «program» по ошибке было набрано как «prgoram», то компилятор сообщит об ошибках:
$ gfortran hello3.f90 hello.f90:1:0: 1 | prgoram hello | Error: Unclassifiable statement at (1) hello3.f90:3:17: 3 | end program hello | 1 Error: Syntax error in END PROGRAM statement at (1) f951: Error: Unexpected end of file in 'hello.f90'
Используя этот отчёт компилятора об ошибках, вы можете исправить текст исходного кода программы и повторить попытку компиляции.
- Выполнение шага сборки без опции «-c» может быть успешным, только если файл исходного кода содержит основную программу, обозначаемую в тексте программы оператором program языка Fortran. В противном случае компоновщик пожалуется на отсутствующий «символ» («symbol») сообщением примерно следующего содержания:
$ gfortran hello2.f90 /usr/lib/../lib64/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status
Файл «hello2.f90» почти такой же как и файл «hello.f90», за исключением того, что ключевое слово program было заменено на ключевое слово subroutine .
Приведённые выше примеры вывода сообщений компилятора будут отличаться в зависимости от используемых компилятора и платформы, на которых он работает. Рассмотренные примеры взяты для компилятора gfortran, работающего в среде Cygwin в Windows.
Компиляторы также отличаются по поддерживаемым ими опциям, но в целом они все имеют:
- Опции для оптимизации кода – в результате их использования программы работают быстрее или занимают меньше памяти;
- Опции для проверки исходного кода – например, проверяется, не используется ли переменная до присвоения ей значения, или проверяется, не используется ли какое-либо расширение языка программирования;
- Опции для указания места расположения подключаемых файлов или файлов модулей, см. далее;
- Опции для отладки.
so the DOM is not blocked -->
© Copyright 2020-2022, Fortran Community.
