сохранить файл в новую папку makefile [duplicate]

Нет, == между Integer, Long и т. д. будет проверяться на ссылочное равенство - то есть

Integer x = ...;
Integer y = ...;

System.out.println(x == y);

, это будет проверять, относятся ли x и y к тот же объект , а не , равный объектам.

Таким образом,

Integer x = new Integer(10);
Integer y = new Integer(10);

System.out.println(x == y);

гарантированно печатает false. Интерполяция «малых» значений автобокса может привести к сложным результатам:

Integer x = 10;
Integer y = 10;

System.out.println(x == y);

Это будет печатать true из-за правил бокса ( JLS раздел 5.1.7 ) , По-прежнему используется ссылочное равенство, но ссылки действительно равны .

Лично я бы использовал:

if (x.intValue() == y.intValue())

или

if (x.equals(y))

Последнее немного менее эффективно - нет перегрузки для Integer.equals(Integer), поэтому ему придется выполнять проверку типа времени выполнения, тогда как первый использует тот факт, что мы уже знаем, что оба объекта Integer s.

К счастью, compareTo знает о типах, поэтому:

if (x.compareTo(y) < 0)

все равно будет эффективным. Конечно, это область микрооптимизации, и вы должны использовать код, который вы найдете наиболее ясным - после того, как убедитесь, что он прав:)

Как вы говорите, для любого сравнения между типом оболочки (Integer, Long и числовой тип (int, long и т. д.) значение типа оболочки - unboxed , и тест применяется к примитивным значениям.

происходит как часть двоичной цифровой рекламы ( JLS раздел 5.6.2 ). Посмотрите документацию каждого отдельного оператора, чтобы узнать, применяется ли она. Например, из документов для == и! = ( JLS 15.21.1 ):

Если операнды оператора равенства являются как числовыми, так и один из них имеет числовой тип, а другой является конвертируемым (п. 5.1.8) в числовой тип, двоичная цифровая продвижение выполняется в операндах (§5.6.2).

и для & lt; , & lt; =,> and> = ( JLS 15.20.1 )

Тип каждого из операндов оператора цифрового сравнения должен быть типом, который является (§5.1.8) к примитивному числовому типу, или возникает ошибка времени компиляции. Бинарное числовое продвижение выполняется в операндах (§5.6.2). Если продвинутый тип операндов является int или long, выполняется сопоставление целого числа со знаком; если этот продвинутый тип является float или double, выполняется сравнение с плавающей запятой.

Обратите внимание, что ничто из этого не рассматривается как часть ситуации, когда ни тип является числовым.

71
задан Jabez 23 December 2009 в 06:58
поделиться

8 ответов

Это сделало бы это - предполагая среду, подобную Unix.

MKDIR_P = mkdir -p

.PHONY: directories

all: directories program

directories: ${OUT_DIR}

${OUT_DIR}:
        ${MKDIR_P} ${OUT_DIR}

Это должно быть запущено в каталоге верхнего уровня - или определение $ {OUT_DIR} должно быть правильно относительно того, где он запускается. Конечно, если вы будете следовать указателям статьи « Recursive Make Considered Harmful » Питера Миллера, вы все равно будете запускать make в каталоге верхнего уровня.

I ' m играл с этим (RMCH) на данный момент. Это потребовало некоторой адаптации к набору программного обеспечения, которое я использую в качестве площадки для тестирования. В пакете есть дюжина отдельных программ, построенных с распространением источника по 15 каталогам, часть из которых разделена. Но с небольшой осторожностью это можно сделать. OTOH, это может быть неприемлемо для новичков.


Как отмечено в комментариях, перечисление команды «mkdir» как действие для «каталогов» неверно. Как также отмечено в комментариях, есть другие способы исправить ошибку «не знаю, как сделать вывод / отладочную ошибку». Один из них - удалить зависимость от линии «каталогов». Это работает, потому что «mkdir -p» не генерирует ошибок, если все каталоги, которые его просят создать, уже существуют. Другой показан механизм, который будет пытаться создать каталог, если он не существует. Версия «с поправками» - это то, что я имел в виду прошлой ночью, - но обе эти методы работают (и у обоих есть проблемы, если существует выход / debug, но это файл, а не каталог).

64
ответ дан Joey Dumont 26 August 2018 в 00:06
поделиться
  • 1
    Спасибо, Джонатан. когда я попробовал, чтобы я получил ошибку & quot; make: *** Нет правила для создания целевых output/debug', needed by каталогов. Stop & Quot. Но теперь я не буду беспокоиться об этом. будет придерживаться основных правил. :). Спасибо за руководство. И я запускаю & quot; make & quot; из каталога топлекса. – Jabez 23 December 2009 в 07:49
  • 2
    Просто удалите $ {OUT_DIR} за каталогами :, тогда он должен работать. – Doc Brown 23 December 2009 в 08:02
  • 3
    Это сработало. Спасибо, Док. – Jabez 23 December 2009 в 09:41
  • 4
    Реализация этого требует, чтобы вы поймали все возможные случаи, когда вы используете каталоги из командной строки. Кроме того, вы не можете создавать правила сборки файлов, зависящие от directories, не заставляя их всегда перестраивать. – mtalexan 30 December 2013 в 20:30
  • 5
    @mtalexan Вы предоставили пару комментариев, объясняющих, что не так с некоторыми из этих ответов, но вы не предложили альтернативный ответ. Тревожно услышать ваше решение этой проблемы. – Samuel 22 September 2015 в 18:58

make внутри и сам по себе обрабатывает цели каталога так же, как и целевые файлы. Таким образом, легко написать такие правила:

outDir/someTarget: Makefile outDir
    touch outDir/someTarget

outDir:
    mkdir -p outDir

Единственная проблема заключается в том, что временная метка каталогов зависит от того, что делается с файлами внутри. Для приведенных выше правил это приводит к следующему результату:

$ make
mkdir -p outDir
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget

Это определенно не то, что вы хотите. Всякий раз, когда вы касаетесь файла, вы также прикасаетесь к каталогу. И поскольку файл зависит от каталога, файл, следовательно, выглядит устаревшим, заставляя его перестраивать.

Однако вы можете легко разбить этот цикл, указав make, чтобы игнорировать временную метку каталога , Это делается путем объявления каталога как только prerqusite для заказа:

# The pipe symbol tells make that the following prerequisites are order-only
#                           |
#                           v
outDir/someTarget: Makefile | outDir
    touch outDir/someTarget

outDir:
    mkdir -p outDir

Это правильно дает:

$ make
mkdir -p outDir
touch outDir/someTarget
$ make
make: 'outDir/someTarget' is up to date.

TL; DR:

Напишите правило для создания каталога:

$(OUT_DIR):
    mkdir -p $(OUT_DIR)

И цели для содержимого внутри зависят от каталога только для заказа:

$(OUT_DIR)/someTarget: ... | $(OUT_DIR)
1
ответ дан cmaster 26 August 2018 в 00:06
поделиться

Все решения, в том числе принятые, имеют некоторые проблемы, как указано в их соответствующих комментариях. Принимаемый ответ by @ jonathan-leffler уже неплохой, но не предполагает, что предпосылки не обязательно должны быть построены по порядку (например, во время make -j). Однако простое перемещение предпосылки directories с all до program провоцирует перестройки на каждом запуске AFAICT. Следующее решение не имеет этой проблемы, и AFAICS работает по назначению.

MKDIR_P := mkdir -p
OUT_DIR := build

.PHONY: directories all clean

all: $(OUT_DIR)/program

directories: $(OUT_DIR)

$(OUT_DIR):
    ${MKDIR_P} $(OUT_DIR)

$(OUT_DIR)/program: | directories
    touch $(OUT_DIR)/program

clean:
    rm -rf $(OUT_DIR)
5
ответ дан Community 26 August 2018 в 00:06
поделиться

учитывая, что вы новичок, я бы сказал, не пытайтесь это сделать. это определенно возможно, но бесполезно усложнит ваш Makefile. придерживайтесь простых способов, пока вам не станет удобнее делать.

, который сказал, один из способов создания в каталоге, отличном от исходного каталога, - VPATH ; Я предпочитаю правила шаблона

2
ответ дан just somebody 26 August 2018 в 00:06
поделиться

Или, KISS.

DIRS=build build/bins

... 

$(shell mkdir -p $(DIRS))

Это создаст все каталоги после анализа файла Makefile.

11
ответ дан Nick Zalutskiy 26 August 2018 в 00:06
поделиться
  • 1
    Мне нравится этот подход, потому что мне не нужно загромождать каждую цель командами для обработки каталогов. – Ken Williams 28 November 2017 в 18:01
  • 2
    Мне просто нужно было создать каталог, если он не существует. Этот ответ подходит для моей проблемы. – jefferson ferreira palheta 3 May 2018 в 17:21
  • 3
    Не только это предотвращает изменение временных меток каждого каталога при запуске ненужного шага сборки. Это должен быть ответ – Assimilater 24 May 2018 в 16:53
  • 4
    Это лучше: $(info $(shell mkdir -p $(DIRS))) Без $(info ...) вывод команды mkdir будет вставлен в Makefile , что в лучшем случае приведет к синтаксическим ошибкам. Вызов $(info ...) гарантирует, что: а) ошибки (если они есть) видны пользователю, и б) что вызов функции расширяется до нуля. – cmaster 28 June 2018 в 11:38

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

re, ориентируясь на обычный или «узорный» файл, просто используйте внутреннюю переменную make $(@D), что означает «каталог, в котором находится текущая цель» (cmp. с $@ для цели). Например,

$(OUT_O_DIR)/%.o: %.cpp
        @mkdir -p $(@D)
        @$(CC) -c $< -o $@

title: $(OBJS)

Затем вы делаете то же самое: создайте каталоги для всех $(OBJS), но вы сделаете это менее сложным способом.

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


Примечание. Если вы собираетесь использовать его, может быть полезно ввести удобную переменную и использовать make .

dir_guard=@mkdir -p $(@D)

$(OUT_O_DIR)/%.o: %.cpp
        $(dir_guard)
        @$(CC) -c $< -o $@

$(OUT_O_DIR_DEBUG)/%.o: %.cpp
        $(dir_guard)
        @$(CC) -g -c $< -o $@

title: $(OBJS)
108
ответ дан P Shved 26 August 2018 в 00:06
поделиться
  • 1
    Хотя привязка требования к каталогу к файлам является лучшим вариантом, на мой взгляд, ваше решение также имеет существенный недостаток в том, что процесс mkdir будет вызываться файлом make для каждого файла, который был перестроен, большинство из которых не нужно будет создавать снова. Когда он адаптирован для систем, не связанных с Linux, таких как Windows, он фактически вызывает как неблокируемый вывод ошибок, так как нет -p, эквивалентного команде mkdir, и, что более важно, гигантское количество накладных расходов, поскольку вызов оболочки не является минимально инвазивным. – mtalexan 30 December 2013 в 20:27

Я только что придумал довольно разумное решение, которое позволяет вам определять файлы для сборки и создавать каталоги автоматически. Сначала определите переменную ALL_TARGET_FILES, которая содержит имя файла для каждого файла, который будет создан ваш make-файл. Затем используйте следующий код:

define depend_on_dir
$(1): | $(dir $(1))

ifndef $(dir $(1))_DIRECTORY_RULE_IS_DEFINED
$(dir $(1)):
    mkdir -p $$@

$(dir $(1))_DIRECTORY_RULE_IS_DEFINED := 1
endif
endef

$(foreach file,$(ALL_TARGET_FILES),$(eval $(call depend_on_dir,$(file))))

Вот как это работает. Я определяю функцию depend_on_dir, которая принимает имя файла и генерирует правило, которое заставляет файл зависеть от каталога, который его содержит, а затем определяет правило для создания этого каталога, если это необходимо. Затем я использую foreach в call эту функцию для каждого имени файла и eval.

Обратите внимание, что вам понадобится версия GNU make, которая поддерживает eval, что я думаю - версии 3.81 и выше.

4
ответ дан Ryan Thompson 26 August 2018 в 00:06
поделиться
  • 1
    Создание переменной, которая содержит «имя файла для каждого файла, который будет создавать ваш make-файл», является своего рода обременительным требованием - мне нравится определять мои цели на высшем уровне, то, от чего они зависят, и так далее. Наличие плоского списка всех целевых файлов идет вразрез с иерархическим характером спецификации make-файла и не может быть (легко) возможным, когда целевые файлы зависят от вычислений времени выполнения. – Ken Williams 28 November 2017 в 17:59

Независимость ОС важна для меня, поэтому mkdir -p не является опцией. Я создал эту серию функций, которые используют eval для создания целей каталога с предварительным условием в родительском каталоге. Это имеет то преимущество, что make -j 2 будет работать без проблем, поскольку зависимости определены правильно.

# convenience function for getting parent directory, will eventually return ./
#     $(call get_parent_dir,somewhere/on/earth/) -> somewhere/on/
get_parent_dir=$(dir $(patsubst %/,%,$1))

# function to create directory targets.
# All directories have order-only-prerequisites on their parent directories
# https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html#Prerequisite-Types
TARGET_DIRS:=
define make_dirs_recursively
TARGET_DIRS+=$1
$1: | $(if $(subst ./,,$(call get_parent_dir,$1)),$(call get_parent_dir,$1))
    mkdir $1
endef

# function to recursively get all directories 
#     $(call get_all_dirs,things/and/places/) -> things/ things/and/ things/and/places/
#     $(call get_all_dirs,things/and/places) -> things/ things/and/
get_all_dirs=$(if $(subst ./,,$(dir $1)),$(call get_all_dirs,$(call get_parent_dir,$1)) $1)

# function to turn all targets into directories
#     $(call get_all_target_dirs,obj/a.o obj/three/b.o) -> obj/ obj/three/
get_all_target_dirs=$(sort $(foreach target,$1,$(call get_all_dirs,$(dir $(target)))))

# create target dirs
create_dirs=$(foreach dirname,$(call get_all_target_dirs,$1),$(eval $(call make_dirs_recursively,$(dirname))))

TARGETS := w/h/a/t/e/v/e/r/things.dat w/h/a/t/things.dat

all: $(TARGETS)

# this must be placed after your .DEFAULT_GOAL, or you can manually state what it is
# https://www.gnu.org/software/make/manual/html_node/Special-Variables.html
$(call create_dirs,$(TARGETS))

# $(TARGET_DIRS) needs to be an order-only-prerequisite
w/h/a/t/e/v/e/r/things.dat: w/h/a/t/things.dat | $(TARGET_DIRS)
    echo whatever happens > $@

w/h/a/t/things.dat: | $(TARGET_DIRS)
    echo whatever happens > $@

Например, при запуске выше создаются:

$ make
mkdir w/
mkdir w/h/
mkdir w/h/a/
mkdir w/h/a/t/
mkdir w/h/a/t/e/
mkdir w/h/a/t/e/v/
mkdir w/h/a/t/e/v/e/
mkdir w/h/a/t/e/v/e/r/
echo whatever happens > w/h/a/t/things.dat
echo whatever happens > w/h/a/t/e/v/e/r/things.dat
3
ответ дан SimplyKnownAsG 26 August 2018 в 00:06
поделиться
Другие вопросы по тегам:

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