Удалить цели с рецептами не удалось в Makefile

Оператор == проверяет, указывают ли две ссылки на один и тот же объект или нет. .equals() проверьте фактическое содержимое строки (значение).

Обратите внимание, что метод .equals() принадлежит классу Object (суперкласс всех классов). Вам необходимо переопределить его в соответствии с вашим требованием к классу, но для String оно уже реализовано и проверяет, имеет ли две строки одно и то же значение.

  • Случай 1
    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true
    
    Причина: строка литералы, созданные без нуля, хранятся в пуле строк в области перментонов кучи. Таким образом, оба s1 и s2 указывают на один и тот же объект в пуле.
  • Случай 2
    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true
    
    Причина. Если вы создаете объект String с использованием ключевого слова new, ему выделяется отдельное пространство в куче.
1
задан Sergei Shumilin 17 January 2019 в 14:49
поделиться

1 ответ

1120 Не знаю, какую неудачу вы видите, но я боюсь, что для вас это не самый лучший способ. .o Файлы и исполняемый файл ($(OUTPUT)) являются отдельными правилами. Если последнее не удается, первое уже не рассматривается. См. Документацию :

.DELETE_ON_ERROR: Если .DELETE_ON_ERROR упоминается как цель где-либо в make-файле, то make удалит цель правила, если оно изменилось и его рецепт завершается с ненулевым статусом выхода, так же, как и при получении сигнала. См. Ошибки в рецептах .

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

Не уверен, что это было бы неплохо, но если бы вам действительно это было нужно, вы, вероятно, могли бы добиться этого путем рефакторинга вашего make-файла, чтобы в основном иметь прямое exec + objs из правила исходных условий с одним рецептом. Очевидный недостаток: такое правило будет означать изменение одного файла .c, в результате чего все файлы будут перекомпилированы (в основном сводит на нет существенные преимущества использования make).


РЕДАКТИРОВАТЬ: Я немного расширю комментарий, чтобы прояснить. Похоже, что вам нужно: в случае, если файл .c поврежден и сборка не удалась, удалите старый файл .o. Это совершенно не совсем так, как работает .DELETE_ON_ERROR. Если файл .o уже обновлен, а затем правило не выполнено, он удаляет его ( «удаляет цель правила, если оно изменилось» ), но в случае упомянутой синтаксической проблемы, компилятор потерпит неудачу, прежде чем он создаст файл .o.

Итак, если, например, вы обновили свое правило (шаблон) для компиляции, чтобы оно сначала touch присваивало (эффективно обновляет метку времени) файл .o, а затем пытается компилировать. После сбоя вызова компилятора и правила make сочтет, что цель поврежденного корня была обновлена, и удалит ее. В качестве альтернативы вы также можете изменить правило, чтобы сначала попытаться rm получить ожидаемый файл «.o», и в этом случае вам на самом деле не нужно будет использовать .DELETE_ON_ERROR (и если нет изменений в соответствующих источниках, правило делает не привыкать, так что на самом деле это не так страшно, как кажется). В любом случае это не совсем чисто, но ведет к поведению, которое, как я понимаю, вы описываете.

0
ответ дан Ondrej K. 17 January 2019 в 14:49
поделиться
Другие вопросы по тегам:

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