Portable file creation in files

I want to keep some efforts down the lines by creating a fairly general makefile that combines relatively simple C ++ projects for me with the minimal changes needed for the makefile.

So far, I have succeeded, so he will use all the files .cppin the same directory and the specified child directories, put all this in the appropriate structure in a subdirectory, objand put the resulting file in another subdirectory bin. Pretty much what I want.

However, trying to get it so that the required obj and bin directories are created, if they do not exist, this provides akward to get a working cross platform - in particular, I just test Win7 and Ubuntu (I can’t remember the version), and cannot make it work on both at the same time. Windows reads mkdir -p dirand creates the directory incorrectly -p, and obviously both platforms use \and /respectively for the path separator - and I get errors when using the wrong one.

Here are a few highlighted parts of the makefile that matter:

#manually edited directories (in this EG 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 $@

This was compiled by me over the past week or so of the things that I read (mainly on SO), so if it happens, I follow some terrible bad practice or something like that, please let me know .

:
makefile , ?

+3
3

Windows mkdir , Unix mkdir -p. $(subst). , Windows :

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

Unix :

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

make . Autoconf.

@command make . , , , .

+6

autoconf. , , . zwol , Windows mkdir , mkdir -p Linux. make. -flag , :

-mkdir dir

, . , "always true" , 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.

. , .

. :

+4

I solved the portability problem by creating a Python script called mkdir.pyand calling it from the Makefile. The limitation is that Python must be installed, but this is most likely true for any version of 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
0
source

Source: https://habr.com/ru/post/1754224/


All Articles