Компиляция C/C++ кодирует посредством включения инструкций по сборке препроцессора в фактическом исходном файле C/C++

  1. Если вам нужно сохранить промежуточный файл после завершения обработки, затем межпроцессная связь (например, через трубу или розетку). не особенно ценна.  Точно так же, если вам нужно запустить две программы в очень разное время, ты должен сделать это так, как делаешь сейчас.
  2. В то время, когда был создан Unix, диски были очень маленькими, и это было обычным делом для довольно доброй команды. потреблять все свободное место в файловой системе. Например,

    some_command_that_produces_a_lot_of_output | grep some_very_obscure_string

    производит вывод, который намного меньше, чем размер вывода первой команды (т.е. размер промежуточного файла, который будет создан если вы запустили команды так же, как вы запускаете свои программы).

  3. Данные, проходящие по трубам и сокетам, (вероятно) вообще не записываются на диск.  Поэтому эти IPC-решения могут быть

    • более эффективными (быстрее), чем дисковые решения.
    • более безопасным, чем дисковые решения, если промежуточные данные более конфиденциальны, чем конечный результат.
0
14.01.2019, 00:19
4 ответа

Главная точка входа - Бог. Будь то исходный файл C или C ++, он является центром приложения.

Только так, как азот является центром сосны . Здесь все начинается , но в C или C ++ нет ничего, что заставляло бы вас поместить «центр» вашего приложения в main () .

Очень много программ на C и C ++ построено на цикле событий или на насосе ввода-вывода . Это «центры» таких программ. Вам даже не нужно помещать эти циклы в тот же модуль , что и main () .

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

На самом деле проще всего поместить main () last в исходный файл C или C ++.

C и C ++ не похожи на некоторые языки, где символы могут использоваться до их объявления. Ввод main () в первую очередь означает, что вы должны объявить вперед-объявить все остальное.

Было время, когда частные библиотеки и библиотеки с закрытым исходным кодом были обычным явлением. Благодаря тому, что Apple перешла на Unix, а Microsoft стреляла себе в ногу, это время прошло.

« Скажи, что мне снится! »

OS X и iOS полны проприетарного кода, и Microsoft в ближайшее время не уйдет.

Какое отношение к вашему вопросу имеют текущие трудности Microsoft? Вы говорите, что, возможно, захотите создавать библиотеки DLL, и упоминаете неспособность Automake эффективно справляться с Windows. Это говорит о том, что Microsoft остается актуальной и в вашем мире.

Статическая линковка - настоящая сука.

Правда? Мне всегда было проще , чем связываться с динамическими библиотеками. Это более старая и простая технология, в которой меньше ошибок.

Статическая компоновка включает внешние зависимости в исполняемый файл, так что исполняемый файл стоит отдельно, самодостаточно. Судя по остальной части вашего вопроса, это должно вас заинтересовать.

вы можете # включать библиотеки как заголовки

Нет ... Вы #include заголовки библиотек , а не библиотеки.

Это не просто педантизм. Терминология имеет значение . Это имеет значение.

Если бы вы могли #include библиотеки, #include работал бы.

Во многих языках программирования это способ работы внешних ссылок на модули / библиотеки. То есть вы напрямую ссылаетесь на внешний код.

C и C ++ не входят в число языков, которые работают таким образом.

Если библиотека C не была разработана для соответствия синтаксису C ++, вы облажались.

Нет, вам просто нужно научиться использовать C ++. В частности, здесь extern «C» .

Как я могу написать такое на жаргоне препроцессора?

Совершенно законно #include другой файл C или C ++:

#include <some/library/main.cpp>

#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>

#include <iostream>

int main()
{
   call_the_library();
   do_other_stuff();
   return 0;
}

Мы не используем здесь extern «C» , потому что это извлекает код C и C ++ из эти другие библиотеки прямо в наш файл C ++, поэтому модули C также должны быть легальными для C ++. Есть ряд досадных небольших различий между C и C ++ , но если вы собираетесь смешивать эти два языка, вам придется знать, как с ними справиться, несмотря ни на что.

Другая сложная часть выполнения этого состоит в том, что порядок #includes более чувствителен, чем порядок ссылок на библиотеки в команде компоновщика. Когда вы обходите компоновщик таким образом, вам приходится делать некоторые вещи вручную, которые в противном случае компоновщик делал бы за вас автоматически.

Чтобы доказать свою точку зрения, я взял MiniBasic (ваш собственный пример) и преобразовал его программу драйвера script.c в автономную программу C ++, которая говорит #include вместо #include . ( patch ) Чтобы доказать, что теперь это действительно программа на C ++, я изменил все вызовы printf () на вставки потока cout .

Мне пришлось внести еще несколько изменений, все они в рамках обычного рабочего дня для того, кто собирается смешивать C и C ++:

  1. Код MiniBasic использует готовность C допускать автоматические преобразования из void * на любой другой тип указателя. C ++ заставляет вас быть откровенным.

  2. Новые компиляторы больше не допускают использование строковых констант C (например, «Hello, world! \ N» ) в контекстах char * . Стандарт говорит, что компилятору разрешено помещать их в постоянную память, поэтому вам нужно использовать const char * .

Вот и все. Всего несколько минут работы, исправление жалоб GCC.

Мне пришлось внести некоторые изменения в basic.c , аналогичные изменениям в связанном файле патча script.c . Я не стал публиковать различия, потому что они почти такие же.

Другой способ сделать это - изучить SQLite Amalgamation по сравнению с деревом исходных текстов SQLite .SQLite не использует #include все остальные файлы в один главный файл; на самом деле они объединены вместе, но это также все, что #include делает в C или C ++.

6
28.01.2020, 02:13

Нет, ты не можешь этого сделать. Нет gcc прагмы для компиляции таким образом . Наиболее похожим является Microsoft Visual C++ #pragma comment(lib, ...) или #pragma comment(linker, ...) [1]]. [2]] за указание на то, что некоторые библиотеки должны быть включены в процедуру линковки.

Привет, GCC. Как дела? Если Вы забыли, то этот исходный файл на который вы сейчас смотрите, написано на C++. Вы, конечно же, должны скомпилируйте его с G++. Есть еще один файл, который нужен этому файлу, но... написано на C. Называется "lolcats.c". Я хочу, чтобы ты составил это один с GCC в объектном файле, и я хочу, чтобы вы скомпилировали этот. с G++ в основной объектный файл, затем я хочу, чтобы вы связали их. вместе в исполняемый файл.

Ваша просьба - это именно то, что делает Makefile.

Вы можете создать скрипт оболочки, который будет извлекать исходные файлы и компилировать их любой командой, которую вы захотите использовать. Но это The Wrong Solution™

Если у Вас несколько файлов, сохраните их как несколько файлов. Если Вы хотите, чтобы люди не использовали команды make или cmakake, не предоставляйте Makefile/CMakefile. Дайте им, например, файл компилировать-me.sh.

Единственный случай, когда я чувствую, что нахожусь в похожей ситуации, это когда я кодирую утилиту в одном файле, но я просто предоставляю команду компиляции сверху внутри комментария.

1
28.01.2020, 02:13

gcc будет компилировать C, C и C ++ как C ++ просто в результате того, что вы правильно называете файлы, препроцессор не вмешивается в это. Однако вам понадобятся блоки extern «C» вокруг ваших объявлений C в ваших файлах C ++, чтобы убедиться, что компоновщик может правильно связывать материалы.

Но то, что вы описываете, почти никогда не поможет. Если вы используете библиотеку, для которой в первую очередь требуется какая-то конфигурация, она все равно понадобится, если вы просто попытаетесь скомпилировать файлы прямо в свой проект. Не так много реальных нетривиальных библиотек представляют собой чистый ISO C, который будет компилироваться на каждой платформе без изменений или какого-либо скрипта конфигурации, поэтому большую часть времени вы будете создавать сложность, а не уменьшать ее, потому что вы собираетесь придется как-то разобраться с этой конфигурацией в вашей собственной сборке.

1
28.01.2020, 02:13

Вы можете решить, что все ваши вещи являются плагинами. Затем скомпилируйте их с помощью gcc -shared -fPIC -O thing1.cc -o thing1.so и пусть основная программа-заглушка выполняет dlopen (3) на ./ thing1. так затем dlsym на God ; в Linux у вас могут быть binfmt_misc уловки, чтобы сделать это более прозрачным.

Если вы настаиваете на использовании самодостаточных программ, обратите внимание, что в GCC есть опция -ffreestanding . Затем вы должны предоставить среду выполнения (по крайней мере, для некоторых базовых операций ввода-вывода через системные вызовы , с которыми вам потребуется взаимодействовать, см. syscalls (2) ). Внимательно изучите соответствующую спецификацию ABI . Для Linux / x86-64 это здесь . Прочтите о соглашениях о вызовах .

Вы также можете настроить GCC с помощью плагинов компилятора, таких как MELT (тогда вы можете добавить #pragma , который будет делать произвольные действия, возможно, даже разветвляя gcc ...)

Кстати, точка входа , такая как ваш God , не является исходным файлом, а является некой меткой, известной компоновщику.

Дополнительная информация о компиляторах , компоновщиках (см. книгу Левина: компоновщики и загрузчики , объектные файлы , ] ELF , библиотеки и общие объекты (см. статью Дреппера : Как писать общие библиотеки ...), crt0.o следует

См. также проект предложения модуля C ++ N3347

0
28.01.2020, 02:13

Теги

Похожие вопросы