Портативный makefile создание каталогов - PullRequest
3 голосов
/ 12 июля 2010

Я пытаюсь сэкономить некоторые усилия в дальнейшем, создав довольно общий make-файл, который соберет для меня относительно простые проекты C ++ с минимальными изменениями, необходимыми для make-файла.

Пока что я 'мы получили его, поэтому он будет использовать все файлы .cpp в одном и том же каталоге и указанных дочерних каталогах, поместит все эти данные в соответствующую структуру в подкаталог obj и поместит полученный файл в другой подкаталог с именем bin.Почти то, что я хочу.

Однако попытка получить его так, чтобы необходимые каталоги obj и bin создавались, если их не было, создает неудобство для работы кроссплатформенно - в частности, я простотестирование с Windows 7 и Ubuntu (не помню версию), и я не могу заставить его работать на обоих одновременно.

Windows неправильно читает mkdir -p dir и создает каталог -p и, очевидно,две платформы используют \ и / соответственно для разделителя пути - и я получаю ошибки при использовании неправильной.

Вот несколько выбранных частей make-файла, которые имеют отношение:

# Manually edited directories (in this example with forward slashes)
SRC_DIR = src src/subdir1 src/subdir2

# Automagic object directories + the "fixed" bin directory
OBJ_DIR = obj $(addprefix obj/,$(SRC_DIR))
BIN_DIR = bin

# Example build target
debug: checkdirs $(BIN)

# At actual directory creation
checkdirs: $(BIN_DIR) $(OBJ_DIR)
$(BIN_DIR):
    @mkdir $@

$(OBJ_DIR):
    @mkdir -p $@

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

Вопрос в двух словах:

Есть ли простой способ заставить создание этого каталога работать из одного make-файла таким образом, чтобы pобеспечивает максимально возможную портативность?

Ответы [ 3 ]

7 голосов
/ 14 мая 2015

Я не знаю автоконф.Каждый опыт, который у меня был с этим, был утомительным.Проблема с решением zwol заключается в том, что в Windows mkdir возвращает ошибку, в отличие от mkdir -p в Linux.Это может нарушить ваше правило.Обходной путь - игнорировать ошибку с флагом - перед командой, например:

-mkdir dir

Проблема в том, что make по-прежнему выдает уродливое предупреждение для пользователя.Обходной путь для этого состоит в том, чтобы выполнить команду «всегда истинно» после сбоя mkdir, как описано здесь , например:

mkdir dir || true

Проблема в том, что Windows и Linuxу меня другой синтаксис для true .

В любом случае, я потратил слишком много времени на это.Я хотел файл make, который работал бы как в POSIX-подобных средах, так и в Windows.В конце я придумал следующее:

ifeq ($(shell echo "check_quotes"),"check_quotes")
   WINDOWS := yes
else
   WINDOWS := no
endif

ifeq ($(WINDOWS),yes)
   mkdir = mkdir $(subst /,\,$(1)) > nul 2>&1 || (exit 0)
   rm = $(wordlist 2,65535,$(foreach FILE,$(subst /,\,$(1)),& del $(FILE) > nul 2>&1)) || (exit 0)
   rmdir = rmdir $(subst /,\,$(1)) > nul 2>&1 || (exit 0)
   echo = echo $(1)
else
   mkdir = mkdir -p $(1)
   rm = rm $(1) > /dev/null 2>&1 || true
   rmdir = rmdir $(1) > /dev/null 2>&1 || true
   echo = echo "$(1)"
endif

Функции / переменные используются следующим образом:

rule:
    $(call mkdir,dir)
    $(call echo,  CC      $@)
    $(call rm,file1 file2)
    $(call rmdir,dir1 dir2)

Обоснование определений:

  • mkdir : исправить путь и игнорировать любые ошибки.
  • del : в Windows del не удаляет файлы, еслиодин из файлов указан в каталоге, который не существует.Например, если вы попытаетесь удалить набор файлов, и dir/file.c будет в списке, но dir не существует, файлы не будут удалены.Эта реализация решает эту проблему, вызывая del один раз для каждого файла.
  • rmdir : исправьте путь и игнорируйте все ошибки.
  • echo : внешний вид вывода сохраняется и не показывает постороннего "" в Windows.

Я потратил много времени на это.Возможно, мне было бы лучше потратить свое время на изучение автоконф.

См. Также:

  1. OS, определяющая make-файл
6 голосов
/ 16 июля 2010

Windows mkdir всегда делает то, что делает Unix mkdir с включенным -p.И вы можете справиться с проблемой обратной косой черты с помощью $ (subst).Итак, в Windows вам нужно следующее:

$(BIN_DIR) $(OBJ_DIR):
        mkdir $(subst /,\\,$@)

, а в Unix вы хотите следующее:

$(BIN_DIR) $(OBJ_DIR):
        mkdir -p -- $@

Выбор между ними нецелесообразен в рамках make-файла.Это то, для чего предназначен Autoconf.

В качестве примечания никогда не используйте функцию @command в своих файлах сборки.Придет день, когда вам нужно будет отладить процесс сборки на машине, к которой у вас нет прямого доступа, и в этот день вы пожалеете об этом.

0 голосов
/ 02 января 2012

Я решил проблему переносимости, создав скрипт на Python с именем mkdir.py и вызвав его из Makefile.Ограничение состоит в том, что Python должен быть установлен, но это, скорее всего, верно для любой версии UNIX.

#!/usr/bin/env python

# Cross-platform mkdir command.

import os
import sys

if __name__=='__main__':
    if len(sys.argv) != 2:
        sys.exit('usage: mkdir.py <directory>')
    directory = sys.argv[1]
    try:
        os.makedirs(directory)
    except OSError:
        pass
...