editline/history.h и editline/readline.h не найдены / не работают на OSX при попытке скомпилировать с уже установленными инструментами разработчика

Я работаю над этим руководством по созданию собственного LISP ( http://www.buildyourownlisp.com/chapter4_interactive_prompt) и по какой-то причине, когда я пытаюсь скомпилировать, я получаю следующее:

REPL.c:4:10: fatal error: 'editline/readline.h' file not found
#include <editline/history.h>
^
1 error generated.

Я установил инструменты разработчика osx, и brew показывает, что readline установлен, и он не знает, что делать, когда я пытаюсь установить brew install editline.

Это мой код:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <editline/readline.h>
  4 #include <editline/history.h>
  5 
  6 int main(int argc, char** argv) {
  7      
  8   /* version/exit info */
  9   puts("Edward Version 0.0.1");
 10   puts("Press Ctrl+c to Exit\n");
 11          
 12   /* endless loop for main REPL */
 13   while (1) { 
 14     /* output prompt and read line */
 15     char* input = readline("lispy> ");
 16                   
 17     /* put input in history  */
 18     add_history(input);
 19                       
 20     /* Echo input back */                          
 21     printf("No you're a %s\n", input);
 22                       
 23     /* free input */
 24     free(input);
 25   }                           
 26   return 0;
 27 } 

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

cc -std=c99 -Wall REPL.c -ledit -o REPL

9 ответов

Решение

Включить только

#include <editline/readline.h>

который должен существовать, если установлены инструменты командной строки. Этот файл содержит "оболочку readline" для libedit, включая функции истории. Включаемый файл <editline/history.h> не существует на OS X.

Я протестировал ваш код с этой модификацией, и он скомпилирован и работает без проблем.

Использование OSX Yosemite. Я удалил #include<editline/history.h>

а затем использовал cc -std=c99 -Wall test.c -ledit -o test

Теперь работает нормально

Я на Эль-Капитане, Удалить #include <editline/history.h>и использовать cc -std=c99 -Wall test.c -ledit -o test работает для меня.
Добавьте флаг -ledit перед выходным фладом, это процесс связывания, позволяющий компилятору напрямую встраивать вызовы editline в вашу программу. Или вы получите следующее сообщение об ошибке,

Undefined symbols for architecture x86_64:
  "_add_history", referenced from:
      _main in prompt-086f90.o
  "_readline", referenced from:
      _main in prompt-086f90.o
ld: symbol(s) not found for architecture x86_64

Я на Ubuntu 14.04.

попробуй это:

sudo apt-get install libeditline-dev

и включить как это:

#include <editline.h>

наконец скомпилируйте так:

добавлять -leditline во флаге

Я надеюсь, что это может помочь.

Я на OSX Mavericks и удаление строки работал для меня:

#include <editline/history.h>

В Debian Buster 10 мне пришлось установить пакет с помощью:

sudo apt install libeditline-dev 

Вместо:

#include <editline/readline.h>
#include <editline/history.h>

Я только что включил:

#include <editline.h>

запускал программу с флагом -leditline и работал отлично.

Если вы используете Ubuntu, добавьте библиотеку editline.sudo apt-get install libtedit-dev

Я начал создавать свой собственный список и столкнулся с той же проблемой. Ни один из приведенных выше ответов не помог мне. После небольшого исследования я обнаружил, что у macO нет библиотеки gnu readline, которая обеспечивает функции readline. Различные версии MacOs обеспечивают эмуляцию readline, используя библиотеку editline. начать...

man editline

#include <histedit.h>

Хорошо, editline дает вам некоторые структуры для ввода строки и истории, а также функции для работы с ними. Сначала вы должны создать эти структуры. Документация для editline не очень полезна, потому что она не содержит примеров. Apple делает доступным заголовочный файл, так что это немного помогает. http://www.opensource.apple.com/source/libedit/libedit-13/src/histedit.h

Я новичок в этом, и это все еще было довольно запутанным для меня. Существует некоторая версия исходного кода для libedit, доступная в виде пакета debian. К счастью, кто-то более мудрый, чем я, уже покопался в ней и реализовал командную строку, используя lbedit Его код здесь: https://www.cs.utah.edu/~bigler/code/libedit.html. Я взял код мистера Биглера и код из своего собственного списка и собрал их вместе, чтобы получить это.

/* repl-macos.c
 * Repl code example from builyourownlisp.com
 * Modified by NB aug 2017
 * Code example for editline from
 * www.cs.utah.edu/~bigler/code/libedit.html
 */

#include <stdio.h>
#include <string.h>
#include <histedit.h>

char* prompt(EditLine *e){
return "lispy> ";
}

int main(int argc, char** argv){

    EditLine *el; // Line editor state
    History *herstory; // the rest is history

    // Temp Variables   
    int count;
    const char *usrin;
    int keepreading = 1;
    HistEvent ev;

    // Initialize the editline state
    el = el_init(argv[0], stdin, stdout, stderr);
    el_set(el, EL_PROMPT, &prompt);
    el_set(el, EL_EDITOR, "emacs");

    // Initialize history
    herstory = history_init();
    if(!herstory){
        fprintf(stderr, "Couldn't initialize history\n");
        return 1;
    }

    //set history size
    history(herstory, &ev, H_SETSIZE, 800);
    // Set up the call back functions for history functionality
    el_set(el, EL_HIST, history, herstory);

    puts("Begin moLisp interpreter");
    puts("Type 'exit' at prompt to exit");

    while(keepreading){
        usrin = el_gets(el, &count);

    // add the command to the history, and echo it back to the user
        if(count > 0){
            history(herstory, &ev, H_ENTER, usrin);
            if(strcmp(usrin, "exit\n"))
                printf("No, You're a %s", usrin);
            else{
                puts("bye");
                --keepreading;
            }
        }   
    }

  // Clean up memory 
  // by freeing the memory pointed to within the structs that
  // libedit has created.
  history_end(herstory);
  el_end(el);


  return 0;
}

Примечание: создание экземпляров используемых структур происходит вне цикла while, как и функции, освобождающие память, которую используют эти структуры. Из-за этого я добавил команду для выхода, в противном случае я думаю, что есть утечка памяти, если единственный способ выйти из цикла while - это прерывание программы. Скомпилировать:

gcc repl-macos.c -ledit -Wall -o repl-edit

-ledit необходим для ссылки на строку редактирования

Если это имеет какое-либо отношение, я использую macOs 10.4.11 и вот мой компилятор, вывод gcc --version

powerpc-apple-darwin8-gcc-4.0.0 (GCC) 4.0.0 20041026 (Apple Computer, Inc., сборка 4061)

Теперь единственная проблема с этим, и книга указывает на это, состоит в том, что c-код должен быть переносимым, а это не так. Следующим шагом будет добавление директив препроцессора, чтобы он использовал readline в linux и editline в macos.

Решение для тех, кто следует за FreeBSD (может работать и на других Unix):

#include <stdio.h>
#include <stdlib.h>

#include <readline/readline.h>
#include <readline/history.h>

...

И запустить:

$ cc test.c -Wall -std=c99 -lreadline -o test

Без "-lreadline" на этапе компиляции он не будет связан, и вы получите ошибки о неопределенной ссылке на функцию "readline".

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