Пытаюсь собрать программу, которая должна определять
соответствует ли файл формату PNG или нет.
#include <stdio.h>
#include <stdlib.h>
#include "png.h"
FILE *fp;
char header[8];
int main(int argc, char *argv[])
{ fp = fopen("/home/oleg/2.png", "rb");
if (!fp) { printf("Cannot open file."); return(1);}
fread(header, 1, 8, fp);
if ( png_sig_cmp(header, 0, 8) )
{printf("Not a PNG."); return(1); }
fclose(fp);
return EXIT_SUCCESS;
}
"Compile file" работает нормально, но при попытке собрать проект через "Build project" выдаёт ошибку:
denspngc.o: In function `main':
/home/oleg/denspngc/src/denspngc.c:12: undefined reference to `png_sig_cmp'
collect2: ld returned 1 exit status
gmake[2]: *** [denspngc] Ошибка 1
gmake[1]: *** [all-recursive] Ошибка 1
gmake: *** [all] Ошибка 2
*** Exited with status: 2 ***
В чём проблема? Как это исправить?
Об том и вопрос: как? Программа должна динамически собираться с libpng. Все libpng* лежат в /usr/lib/ , и другие программы ими нормально пользуются. Он пытается собрать статически? Где это менять в настройках? Какие ключи gcc и ./configure за это отвечают?
> А вообще советую vim\emacs\еще_что_то_из_ТруЪ + cmake - там всем сам управляешь у лучше въдешь в тему.
Что добавить в vim, чтобы из него можно было пошагово проходить программы ("Trace into"/"Step over"/"Run to") одновременно наблюдая изменение переменных? Или в emacs?
> Что добавить в vim, чтобы из него можно было пошагово проходить программы ("Trace into"/"Step over"/"Run to") одновременно наблюдая изменение переменных? Или в emacs?
Как это следует делать? Я только написал #include "png.h" и убедился, что в настройках прописан путь к /usr/include. Надо ещё где-то указывать /usr/lib ? Где и как?
ты вообще представляешь как программы компилируются? тебе что-нибудь говорит ключик -l у gcc? если нет, то может стоит всё же почитать наконец про всё это?
man gcc
/-l library
-l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX
compliance and is not recommended.)
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in
the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to
functions in z, those functions may not be loaded.
The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then
uses this file as if it had been specified precisely by name.
The directories searched include several standard system directories plus any that you specify with -L.
Normally the files found this way are library files---archive files whose members are object files. The linker handles an archive
file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file
that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and
specifying a file name is that -l surrounds library with lib and .a and searches several directories
Чтобы собрать вручную надо сделать gcc -lpng [другие ключи] -o denspngc denspngc.o . Это я понял. Вопрос был как заставить kdevelop подставлять -lpng автоматически.
> Вопрос был как заставить kdevelop подставлять -lpng автоматически.
Как уже заметил Demon37, стандартным связующим элементом между "хочу использовать X" и "что надо писать во флаги компилятору и линкеру" в линуксе является pkg-config, умеющий выдавать нужную информацию по --cflags и --libs
Компилятор видит, что используется png.h. Компилятор может определить связанную с ним библиотеку libpng и вызвать pkg-config. Или эта связь нигде не прописана?
> стандартным связующим элементом между "хочу использовать X" и "что надо писать во флаги компилятору и линкеру" в линуксе является pkg-config, умеющий выдавать нужную информацию по --cflags и --libs
> Компилятор видит, что используется png.h. Компилятор может определить связанную с ним библиотеку libpng и вызвать pkg-config. Или эта связь нигде не прописана?
А какую конкретно libpng? В /usr/lib, в /usr/local/lib, в ~/mylibpnghack/lib? Какой версии? Статически линковать или динамически? Откуда линкеру знать, что мне нужно?
> Вдогонку: pkg-config в данном случае берёт в качестве аргумента просто libpng без указания путей и версий и справляется.
Потому что добрый дядечка для libpng руками сделал описание, с которым pkg-config и работает. libpng.pkg ставится в /usr/share/pkg-config при установке пакета libpng-devel. Чудес не бывает.
> для libpng руками сделал описание, с которым pkg-config и работает. libpng.pkg ставится в /usr/share/pkg-config при установке пакета libpng-devel. Чудес не бывает.
При чём тут чудеса? Что мешает другим программам использовать эти данные или автоматически вызывать pkg-config?
А кто мешает вам прописать LIBS в configure.in? Да никто! Просто чехарда с этими библиотеками будет неоправдана. У меня например, собирается софт с использованием gtk, но зависящий только от libc. И я не хочу отключать использование библиотек руками.
А еще почти каждый мой исходник содержит в себе #include <cryptoki.h>, а цеплять его не надо, так как токен должен цепляться динамически, хотя mozilla к примеру может установить свой pkcs#11 и прописать pkg-config. Да и вообще, если вы почитаете K&R, то поймете, что это невозможно, так как сам компилятор не в курсе того, что написано в директивах #include.
А почему ты думаешь, что одна библиотека = один заголовочный файл + одинаково называющийся с библиотекой?
Это общем случае совсем не так.
Далее, то, что какие-то файлы принадлежат одному пакету - это информация, связанная с конкретной системой пакетов. Нужно учить менеджеры проектов пользоваться утилитами для работы с пакетами (которые в разных дистрибутивах разные)?
И даже если мы нашли пакет, к которому принадлежит заголовочный файл, что, нужно подключать к нашей программе все библиотечные файлы, которые относятся к этому пакету?
Да, этого нигде нет применительно к С/С++. Потому как в этих языках заголовочные файлы и библиотеки - вещи не связанные.
> Полагаю, в msvs. Поэтому вендовые программеры нечасто компилятор от ide отличают.
Нет, даже там такого нет. Просто там стандартный набор подключаемых библиотек побольше, в настройках проекта в одном из основных разделов есть выбор "Использовать стандартные библиотеки"/"Использовать еще и MFC", а в solution (объединение проектов) можно указать зависимости проектов друг от друга и тогда подключение библиотек, собираемых в том или ином проекте, будет автоматически прописываться в зависимые проекты.
Поэтому прописывать подключение дополнительных библиотечных файлов нужно несколько реже. Хотя мне милее нормальный GNU make - в нем все сам пишешь и все просто и понятно, в отличии от кучи окошек с маловразумительными настройками.
> Другие программы могут работать там, где pkg-config нет
И что с того? Есть -- отлично, подставляет. Нет -- ругается и ничего не делает. Кроме того, много ли систем, где есть KDE, но нет pkg-config?
Или хочется, чтобы с ним взаимодействовал autoconf?
> А почему ты думаешь, что одна библиотека = один заголовочный файл + одинаково называющийся с библиотекой?
Я этого не говорил. (Просто в данном случае имена совпали.) Я ожидал, что даже если в заголовочном файле нет информации к какой библиотеке он относится, эта информация есть где-то ещё, в виде доступном компилятору, IDE или другой программе, работающей с с мейкфайлом. Библиотека и заголовочный файл бесполезны друг без друга, логично автоматизировать их подключение. Вижу, что К-Р и Страуструп считали иначе, и с тех пор никто не счёл нужным добавить эту автоматизацию.
>Я ожидал, что даже если в заголовочном файле нет информации к какой библиотеке он относится, эта информация есть где-то ещё, в виде доступном компилятору, IDE или другой программе, работающей с с мейкфайлом.
Во-первых, компилятор не работает с файлами проекта, более того, он даже ничего не знает про заголовочные файлы.
Во-вторых, ты, возможно, не до конца понимаешь, что такое заголовочные файлы. Они никак с библиотеками не связаны. Можно использовать заголовочные файлы, не относящиеся к каким-либо библиотекам, можно использовать библиотеки без заголовочных файлов. Заголовочный файл - это просто кусок кода, который препроцессор вставляет на место директивы #include. В случае с библиотекой это действие вставляет нужные определения типов и объявления функций, реализация которых находится где-то вовне относительно текущего файла программы. Препроцессору наплевать, что за код он в итоге формирует. Компилятору наплевать, где находятся реализации функций, а о том, что какая-то часть компилируемой программы была вставлена извне - он уже и не знает. Компоновщик тоже ничего не знает о заголовочных файлах и просто обрабатывает поданные ему на вход объектные файлы.
Работу с библиотеками упрощают такие штуки, как pkg-config. Но и они ничего не знают о заголовочных файлах. Ты предлагаешь сделать построитель проекта, который будет анализировать код программы, вылавливать директивы #include, обращаться к системе пакетов дистрибутива и формировать список библиотечных файлов, входящих в тот же пакет, что и тот или иной заголовочный файл.
Но даже если оставить в стороне вопрос о том, что нет четкой и однозначной связи заголовочный файл <-> библиотечный файл, то возникает проблема запрашивания данных о пакете. В дистрибутиве может не быть пакетов. Нет одной системы пакетов. В пакет может входить куча заголовочных файлов и куча библиотечных файлов. Могут быть разные пакеты для заголовочных файлов библиотеки и для динамически подгружаемых файлов кода библиотеки.
Так что идея твоя весьма неоднозначна. Гораздо проще указывать самому, какие именно библиотечные файлы нужно подключать.