web-gelistirme-sc.com

__DATE__ ve __TIME__ önceden tanımlanmış makroları iki tamsayı olarak nasıl kullanıp, sonra stringify'ı nasıl kullanabilirim?

Derleme zamanında koduma otomatik bir sürüm vermek için tam sayı olarak _ DATE __ VE __ TIME _ kullanmak istiyorum.

#define STRINGIZER(arg)     #arg
#define STR_VALUE(arg)      STRINGIZER(arg)

#define DATE_as_int_str useD(__DATE__) // What can be done ?
#define TIME_as_int_str useT(__TIME__) // What can be done ?

#define VERSION 1.4

#define COMPLETE_VERSION STR_VALUE(VERSION) "." DATE_as_int_str "." TIME_as_int_str

ve bir COMPLETE_VERSION içinde dizge olarak const unsigned char [] komutunu alın.

const unsigned char completeVersion[] = ?? COMPLETE_VERSION;

Bir şey çıktı 1.4.1432.2234.

Olası çözümlerden biri olabilir ama işe yaramadı: convert -date -to-işaretsiz-int

Derleme zamanı bağlamında convertint-tarih-ve-time-string-to-just-tamsayılar-in-c Biri başvurabilir: marco-name-not-its-value

34
Rick2047

Sürüm dizginizi içermek istediğiniz nesne dosyasını oluşturmak için bir C++ derleyicisi kullanabilirsiniz, tam olarak ne istersen yapabiliriz! Buradaki tek sihir, C++ 'ın bir diziyi statik olarak başlatmak için ifadeler kullanmanıza izin verdiği ve C'nin yapamayacağıdır. İfadelerin derleme zamanında tamamen hesaplanabilir olması gerekir, ancak bu ifadeler sorun değil.

Her seferinde bir bayt sürüm dizesi hazırlıyoruz ve istediğimizi elde ediyoruz.

// source file version_num.h

#ifndef VERSION_NUM_H

#define VERSION_NUM_H


#define VERSION_MAJOR 1
#define VERSION_MINOR 4


#endif // VERSION_NUM_H

// source file build_defs.h

#ifndef BUILD_DEFS_H

#define BUILD_DEFS_H


// Example of __DATE__ string: "Jul 27 2012"
//                              01234567890

#define BUILD_YEAR_CH0 (__DATE__[ 7])
#define BUILD_YEAR_CH1 (__DATE__[ 8])
#define BUILD_YEAR_CH2 (__DATE__[ 9])
#define BUILD_YEAR_CH3 (__DATE__[10])


#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')


#define BUILD_MONTH_CH0 \
    ((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0')

#define BUILD_MONTH_CH1 \
    ( \
        (BUILD_MONTH_IS_JAN) ? '1' : \
        (BUILD_MONTH_IS_FEB) ? '2' : \
        (BUILD_MONTH_IS_MAR) ? '3' : \
        (BUILD_MONTH_IS_APR) ? '4' : \
        (BUILD_MONTH_IS_MAY) ? '5' : \
        (BUILD_MONTH_IS_JUN) ? '6' : \
        (BUILD_MONTH_IS_JUL) ? '7' : \
        (BUILD_MONTH_IS_AUG) ? '8' : \
        (BUILD_MONTH_IS_SEP) ? '9' : \
        (BUILD_MONTH_IS_OCT) ? '0' : \
        (BUILD_MONTH_IS_NOV) ? '1' : \
        (BUILD_MONTH_IS_DEC) ? '2' : \
        /* error default */    '?' \
    )

#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0')
#define BUILD_DAY_CH1 (__DATE__[ 5])



// Example of __TIME__ string: "21:06:19"
//                              01234567

#define BUILD_HOUR_CH0 (__TIME__[0])
#define BUILD_HOUR_CH1 (__TIME__[1])

#define BUILD_MIN_CH0 (__TIME__[3])
#define BUILD_MIN_CH1 (__TIME__[4])

#define BUILD_SEC_CH0 (__TIME__[6])
#define BUILD_SEC_CH1 (__TIME__[7])


#if VERSION_MAJOR > 100

#define VERSION_MAJOR_INIT \
    ((VERSION_MAJOR / 100) + '0'), \
    (((VERSION_MAJOR % 100) / 10) + '0'), \
    ((VERSION_MAJOR % 10) + '0')

#Elif VERSION_MAJOR > 10

#define VERSION_MAJOR_INIT \
    ((VERSION_MAJOR / 10) + '0'), \
    ((VERSION_MAJOR % 10) + '0')

#else

#define VERSION_MAJOR_INIT \
    (VERSION_MAJOR + '0')

#endif

#if VERSION_MINOR > 100

#define VERSION_MINOR_INIT \
    ((VERSION_MINOR / 100) + '0'), \
    (((VERSION_MINOR % 100) / 10) + '0'), \
    ((VERSION_MINOR % 10) + '0')

#Elif VERSION_MINOR > 10

#define VERSION_MINOR_INIT \
    ((VERSION_MINOR / 10) + '0'), \
    ((VERSION_MINOR % 10) + '0')

#else

#define VERSION_MINOR_INIT \
    (VERSION_MINOR + '0')

#endif



#endif // BUILD_DEFS_H

// source file main.c

#include "version_num.h"
#include "build_defs.h"

// want something like: 1.4.1432.2234

const unsigned char completeVersion[] =
{
    VERSION_MAJOR_INIT,
    '.',
    VERSION_MINOR_INIT,
    '-', 'V', '-',
    BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, BUILD_YEAR_CH3,
    '-',
    BUILD_MONTH_CH0, BUILD_MONTH_CH1,
    '-',
    BUILD_DAY_CH0, BUILD_DAY_CH1,
    'T',
    BUILD_HOUR_CH0, BUILD_HOUR_CH1,
    ':',
    BUILD_MIN_CH0, BUILD_MIN_CH1,
    ':',
    BUILD_SEC_CH0, BUILD_SEC_CH1,
    '\0'
};


#include <stdio.h>

int main(int argc, char **argv)
{
    printf("%s\n", completeVersion);
    // prints something similar to: 1.4-V-2013-05-09T15:34:49
}

Bu tam olarak istediğiniz biçim değil, ancak gün ve saatlerin bir tamsayıya nasıl eşlenmesini istediğinizi tam olarak anlamıyorum. Bunun istenen herhangi bir dizgenin nasıl üretileceğinin oldukça açık olduğunu düşünüyorum.

40
steveha

İşte "build defs" nin çalışan bir versiyonu. Bu benim önceki cevabımın benzerini oluşturuyor ancak yapı ayını çözdüm. (Yapı ayını bir #if ifadesinde hesaplayamazsınız, ancak sabit olarak derlenecek olan üçlü bir ifadeyi kullanabilirsiniz.)

Ayrıca, belgelere göre, derleyici günün saatini alamıyorsa, size bu dizeler için soru işaretleri verecektir. Bu yüzden, bu durum için testler ekledim ve bu olursa, çeşitli makroların açıkça yanlış bir değer (99) döndürmesini sağladım.

#ifndef BUILD_DEFS_H

#define BUILD_DEFS_H


// Example of __DATE__ string: "Jul 27 2012"
// Example of __TIME__ string: "21:06:19"

#define COMPUTE_BUILD_YEAR \
    ( \
        (__DATE__[ 7] - '0') * 1000 + \
        (__DATE__[ 8] - '0') *  100 + \
        (__DATE__[ 9] - '0') *   10 + \
        (__DATE__[10] - '0') \
    )


#define COMPUTE_BUILD_DAY \
    ( \
        ((__DATE__[4] >= '0') ? (__DATE__[4] - '0') * 10 : 0) + \
        (__DATE__[5] - '0') \
    )


#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')


#define COMPUTE_BUILD_MONTH \
    ( \
        (BUILD_MONTH_IS_JAN) ?  1 : \
        (BUILD_MONTH_IS_FEB) ?  2 : \
        (BUILD_MONTH_IS_MAR) ?  3 : \
        (BUILD_MONTH_IS_APR) ?  4 : \
        (BUILD_MONTH_IS_MAY) ?  5 : \
        (BUILD_MONTH_IS_JUN) ?  6 : \
        (BUILD_MONTH_IS_JUL) ?  7 : \
        (BUILD_MONTH_IS_AUG) ?  8 : \
        (BUILD_MONTH_IS_SEP) ?  9 : \
        (BUILD_MONTH_IS_OCT) ? 10 : \
        (BUILD_MONTH_IS_NOV) ? 11 : \
        (BUILD_MONTH_IS_DEC) ? 12 : \
        /* error default */  99 \
    )

#define COMPUTE_BUILD_HOUR ((__TIME__[0] - '0') * 10 + __TIME__[1] - '0')
#define COMPUTE_BUILD_MIN  ((__TIME__[3] - '0') * 10 + __TIME__[4] - '0')
#define COMPUTE_BUILD_SEC  ((__TIME__[6] - '0') * 10 + __TIME__[7] - '0')


#define BUILD_DATE_IS_BAD (__DATE__[0] == '?')

#define BUILD_YEAR  ((BUILD_DATE_IS_BAD) ? 99 : COMPUTE_BUILD_YEAR)
#define BUILD_MONTH ((BUILD_DATE_IS_BAD) ? 99 : COMPUTE_BUILD_MONTH)
#define BUILD_DAY   ((BUILD_DATE_IS_BAD) ? 99 : COMPUTE_BUILD_DAY)

#define BUILD_TIME_IS_BAD (__TIME__[0] == '?')

#define BUILD_HOUR  ((BUILD_TIME_IS_BAD) ? 99 :  COMPUTE_BUILD_HOUR)
#define BUILD_MIN   ((BUILD_TIME_IS_BAD) ? 99 :  COMPUTE_BUILD_MIN)
#define BUILD_SEC   ((BUILD_TIME_IS_BAD) ? 99 :  COMPUTE_BUILD_SEC)


#endif // BUILD_DEFS_H

Aşağıdaki test kodu ile, yukarıdakiler harika çalışıyor:

printf("%04d-%02d-%02dT%02d:%02d:%02d\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY, BUILD_HOUR, BUILD_MIN, BUILD_SEC);

Ancak, bu makroları stringizing makro ile kullanmaya çalıştığımda, değişmez ifadeyi stringize eder! Derleyiciyi, ifadeyi değişmez bir tamsayı değerine indirgemeyi ve ardından dizgileştirmeyi herhangi bir yol bilmiyorum.

Ayrıca, bu makroları kullanarak bir değerler dizisini statik olarak başlatmayı denerseniz, derleyici error: initializer element is not constant mesajıyla şikayet eder. Yani bu makrolarla istediğini yapamazsın.

Bu noktada en iyi seçeneğinizin, sizin için yeni bir dosya ekleyen Python betiği olduğunu düşünüyorum. İstediğiniz herhangi bir formatta istediğiniz herhangi bir formatta önceden hesaplayabilirsiniz. Python'u istemiyorsanız, bir AWK betiği veya bir C programı yazabiliriz.

14
steveha

Sana kısmi bir cevabım var. Bu GCC’den aldığım şeye dayanıyor:

__DATE__, "Jul 27 2012" gibi bir şey verir

__TIME__, 21:06:19 gibi bir şey verir

Bu metni build_defs.h adlı bir dosyaya ekleyin:

#ifndef BUILD_DEFS_H

#define BUILD_DEFS_H


#define BUILD_YEAR ((__DATE__[7] - '0') * 1000 +  (__DATE__[8] - '0') * 100 + (__DATE__[9] - '0') * 10 + __DATE__[10] - '0')

#define BUILD_DATE ((__DATE__[4] - '0') * 10 + __DATE__[5] - '0')


#if 0
#if (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
    #define BUILD_MONTH  1
#Elif (__DATE__[0] == 'F' && __DATE__[1] == 'e' && __DATE__[2] == 'b')
    #define BUILD_MONTH  2
#Elif (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
    #define BUILD_MONTH  3
#Elif (__DATE__[0] == 'A' && __DATE__[1] == 'p' && __DATE__[2] == 'r')
    #define BUILD_MONTH  4
#Elif (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
    #define BUILD_MONTH  5
#Elif (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
    #define BUILD_MONTH  6
#Elif (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
    #define BUILD_MONTH  7
#Elif (__DATE__[0] == 'A' && __DATE__[1] == 'u' && __DATE__[2] == 'g')
    #define BUILD_MONTH  8
#Elif (__DATE__[0] == 'S' && __DATE__[1] == 'e' && __DATE__[2] == 'p')
    #define BUILD_MONTH  9
#Elif (__DATE__[0] == 'O' && __DATE__[1] == 'c' && __DATE__[2] == 't')
    #define BUILD_MONTH 10
#Elif (__DATE__[0] == 'N' && __DATE__[1] == 'o' && __DATE__[2] == 'v')
    #define BUILD_MONTH 11
#Elif (__DATE__[0] == 'D' && __DATE__[1] == 'e' && __DATE__[2] == 'c')
    #define BUILD_MONTH 12
#else
    #error "Could not figure out month"
#endif
#endif

#define BUILD_HOUR ((__TIME__[0] - '0') * 10 + __TIME__[1] - '0')
#define BUILD_MIN ((__TIME__[3] - '0') * 10 + __TIME__[4] - '0')
#define BUILD_SEC ((__TIME__[6] - '0') * 10 + __TIME__[7] - '0')

#endif // BUILD_DEFS_H

Yukarıdakileri Linux'ta GCC ile test ettim. Her şey harika, sorun dışında ay için nasıl bir sayı bulacağımı bulamıyorum. #if 0 altındaki bölümü kontrol ederseniz, ayı anlamaya çalıştığımı görürsünüz. GCC bu mesajla şikayet ediyor:

error: token ""Jul 27 2012"" is not valid in preprocessor expressions

Üç harfli ay kısaltmasını bir tür benzersiz sayıya dönüştürmek önemsizdir; sadece 'A' harfini ilk harften, 'a' harfini ikinci ve üçüncü harflerden çıkartın ve ardından taban-26 rakamına dönüştürün. Ancak Ocak ve bunun için 1 olarak değerlendirilmesini istiyorum ve bunun nasıl yapılacağını çözemiyorum.

EDIT: Tamsayı değerlerini değerlendiren ifadeleri değil, dizeleri istediğinizi fark ettim.

Statik bir dize oluşturmak için bu püf noktalarını kullanmaya çalıştım:

#define BUILD_MAJOR 1
#define BUILD_MINOR 4
#define VERSION STRINGIZE(BUILD_MAJOR) "." STRINGIZE(BUILD_MINOR)

char build_str[] = {
    BUILD_MAJOR + '0', '.' BUILD_MINOR + '0', '.',
    __DATE__[7], __DATE__[8], __DATE__[9], __DATE__[10],
    '\0'
};

GCC, __DATE__ için "başlatıcı öğenin sabit olmadığından" şikayetçi.

Üzgünüm, nasıl yardımcı olacağımdan emin değilim. Belki bu şeyleri derleyicinizle deneyebilirsiniz. Ya da belki sana bir fikir verecektir.

İyi şanslar.

Not; Sayı olmak için bir şeylere ihtiyacınız yoksa ve yalnızca benzersiz bir yapı dizisi istiyorsanız, bu kolaydır:

const char *build_str = "Version: " VERSION " " __DATE__ " " __TIME__;

GCC ile bu, şöyle bir sonuçla sonuçlanır:

Version: 1.4 Jul 27 2012 21:53:59
10
steveha

Python'da her zaman basit bir program veya derleme numarası, saati ve tarihi olan basit #define ifadeleri içeren bir içerme dosyası oluşturmak için bir şeyler yazabilirsiniz. Daha sonra bir derleme yapmadan önce bu programı çalıştırmanız gerekir.

İsterseniz bir tane yazıp buraya kaynak göndereceğim.

Şanslıysanız, derleme aracınız (IDE veya her neyse) harici bir komut çalıştırma yeteneğine sahip olabilir ve ardından harici aracın her dosyayı derleme dosyasında otomatik olarak yeniden yazmasını sağlayabilirsiniz.

EDIT: İşte bir Python programı. Bu, build_num.h adında bir dosya yazar ve 1'de başlayan ve bu program her çalıştırıldığında artan olan bir tam sayı oluşturma sayısına sahiptir; ayrıca, programın çalıştırıldığı zamanın, ayın, tarihin, saatlerin, dakikaların ve saniyelerin #define değerlerini yazar. Ayrıca sürüm numarasının büyük ve küçük bölümleri için bir #define, ayrıca istediğiniz tam VERSION ve COMPLETE_VERSION değerlerine de sahiptir. (Tarih ve saat numaraları için ne istediğinizden emin değildim, bu nedenle tarih ve saatten sadece birleştirilmiş rakamlar için gittim. Bunu kolayca değiştirebilirsiniz.)

Her çalıştırdığınızda, build_num.h dosyasında okur ve derleme numarası için ayrıştırır; build_num.h dosyası yoksa, derleme sayısını 1'de başlatır. Aynı şekilde büyük ve küçük sürüm numaralarını da ayrıştırır ve dosya yoksa, varsayılan sürüm 0.1 olanlara da varsayılandır.

import time

FNAME = "build_num.h"

build_num = None
version_major = None
version_minor = None

DEF_BUILD_NUM = "#define BUILD_NUM "
DEF_VERSION_MAJOR = "#define VERSION_MAJOR "
DEF_VERSION_MINOR = "#define VERSION_MINOR "

def get_int(s_marker, line):
    _, _, s = line.partition(s_marker) # we want the part after the marker
    return int(s)

try:
    with open(FNAME) as f:
        for line in f:
            if DEF_BUILD_NUM in line:
                build_num = get_int(DEF_BUILD_NUM, line)
                build_num += 1
            Elif DEF_VERSION_MAJOR in line:
                version_major = get_int(DEF_VERSION_MAJOR, line)
            Elif DEF_VERSION_MINOR in line:
                version_minor = get_int(DEF_VERSION_MINOR, line)
except IOError:
    build_num = 1
    version_major = 0
    version_minor = 1

assert None not in (build_num, version_major, version_minor)


with open(FNAME, 'w') as f:
    f.write("#ifndef BUILD_NUM_H\n")
    f.write("#define BUILD_NUM_H\n")
    f.write("\n")
    f.write(DEF_BUILD_NUM + "%d\n" % build_num)
    f.write("\n")
    t = time.localtime()
    f.write("#define BUILD_YEAR %d\n" % t.tm_year)
    f.write("#define BUILD_MONTH %d\n" % t.tm_mon)
    f.write("#define BUILD_DATE %d\n" % t.tm_mday)
    f.write("#define BUILD_HOUR %d\n" % t.tm_hour)
    f.write("#define BUILD_MIN %d\n" % t.tm_min)
    f.write("#define BUILD_SEC %d\n" % t.tm_sec)
    f.write("\n")
    f.write("#define VERSION_MAJOR %d\n" % version_major)
    f.write("#define VERSION_MINOR %d\n" % version_minor)
    f.write("\n")
    f.write("#define VERSION \"%d.%d\"\n" % (version_major, version_minor))
    s = "%d.%d.%04d%02d%02d.%02d%02d%02d" % (version_major, version_minor,
            t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
    f.write("#define COMPLETE_VERSION \"%s\"\n" % s)
    f.write("\n")
    f.write("#endif // BUILD_NUM_H\n")

Tüm tanımları sadece tamsayılar yaptım, ancak basit tamsayılar olduklarından, isterseniz bir dizge oluşturmak için standart tel ipuçlarını kullanabilirsiniz. Ayrıca önceden tanımlanmış ek dizeler oluşturmak için önemsiz bir şekilde genişletebilirsiniz.

Bu program, herhangi bir Python 3.x sürümü de dahil olmak üzere Python 2.6 veya daha yenisi altında çalışmalıdır. Dizeyi ayrıştırmak için .partition() işlevini kullanmamak gibi birkaç değişiklikle eski bir Python altında çalıştırabilirsiniz.

6
steveha

Kısa cevap (sorulan versiyon): (format 3.33.20150710.182906)

Lütfen basit bir makefile kullanın:

MAJOR = 3
MINOR = 33
BUILD = $(Shell date +"%Y%m%d.%H%M%S")
VERSION = "\"$(MAJOR).$(MINOR).$(BUILD)\""
CPPFLAGS = -DVERSION=$(VERSION)

program.x : source.c
       gcc $(CPPFLAGS) source.c -o program.x

ve makefile istemiyorsanız, daha kısa, sadece şunu derleyin:

gcc source.c -o program.x -DVERSION=\"2.22.$(date +"%Y%m%d.%H%M%S")\"

Kısa cevap (önerilen sürüm): (biçim 150710.182906)

Sürüm numarası için double kullanın:

MakeFile:

VERSION = $(Shell date +"%g%m%d.%H%M%S")
CPPFLAGS = -DVERSION=$(VERSION)
program.x : source.c
      gcc $(CPPFLAGS) source.c -o program.x

Veya basit bir bash komutu:

$ gcc source.c -o program.x -DVERSION=$(date +"%g%m%d.%H%M%S")

Tip: Hala makefile 'den hoşlanmıyor musunuz, yoksa küçük bir test programı için değil mi? Bu satırı ekle:

 export CPPFLAGS='-DVERSION='$(date +"%g%m%d.%H%M%S")

~/.profile adresinize ekleyin ve gcc $CPPFLAGS ... ile derlemeyi unutmayın.


Uzun cevap:

Bu sorunun daha eski olduğunu biliyorum, ancak yapmam gereken küçük bir katkım var. En iyi uygulama, aksi halde bir hata kaynağı (ya da unutulma) haline gelebilecek olanı otomatikleştirmektir.

Benim için sürüm numarasını oluşturan bir işleve alıştım. Ancak bu işlevi float döndürmek için tercih ederim. Sürüm numaram şu şekilde basılabilir: printf("%13.6f\n", version()); ki bunun gibi bir şey var: 150710.150411 (Yıl (2 basamak) ay günü DOT saat dakika saniye).

Ama, peki, soru sizin. Eğer "major.minor.date.time" tercih ederseniz, bir dizge olması gerekecektir. (Güven bana, iki kat daha iyidir. Eğer büyük bir konuda ısrar ediyorsanız, büyük binayı ayarladıysanız ve ondalık sayıların tarih + saat gibi olmasına izin verirseniz hala çift kullanabilirsiniz: major.datetime = 1.150710150411

Hadi işe gidelim. Her zamanki gibi derlerseniz, ayarlamayı unutursanız veya sürümü doğrudan Shell'den ayarlamak için -DVERSION kullanıyorsanız örnek feryat çalışacaktır, ancak hepsinden iyisi, üçüncü seçeneği tavsiye ederim: use makefile.


Üç derleme şekli ve sonuçları:

Make make:

beco> make program.x
gcc -Wall -Wextra -g -O0 -ansi -pedantic-errors -c -DVERSION="\"3.33.20150710.045829\"" program.c -o program.o
gcc  program.o -o program.x

Koşu:

__DATE__: 'Jul 10 2015'
__TIME__: '04:58:29'
VERSION: '3.33.20150710.045829'

-DVERSION: kullanarak

beco> gcc program.c -o program.x -Wall -Wextra -g -O0 -ansi -pedantic-errors -DVERSION=\"2.22.$(date +"%Y%m%d.%H%M%S")\"

Koşu:

__DATE__: 'Jul 10 2015'
__TIME__: '04:58:37'
VERSION: '2.22.20150710.045837'

Yerleşik işlevi kullanarak:

beco> gcc program.c -o program.x -Wall -Wextra -g -O0 -ansi -pedantic-errors

Koşu:

__DATE__: 'Jul 10 2015'
__TIME__: '04:58:43'
VERSION(): '1.11.20150710.045843'

Kaynak kodu

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #define FUNC_VERSION (0)
  6 #ifndef VERSION
  7   #define MAJOR 1
  8   #define MINOR 11
  9   #define VERSION version()
 10   #undef FUNC_VERSION
 11   #define FUNC_VERSION (1)
 12   char sversion[]="9999.9999.20150710.045535";
 13 #endif
 14 
 15 #if(FUNC_VERSION)
 16 char *version(void);
 17 #endif
 18 
 19 int main(void)
 20 {
 21 
 22   printf("__DATE__: '%s'\n", __DATE__);
 23   printf("__TIME__: '%s'\n", __TIME__);
 24 
 25   printf("VERSION%s: '%s'\n", (FUNC_VERSION?"()":""), VERSION);
 26   return 0;
 27 }
 28 
 29 /* String format: */
 30 /* __DATE__="Oct  8 2013" */
 31 /*  __TIME__="00:13:39" */
 32
 33 /* Version Function: returns the version string */
 34 #if(FUNC_VERSION)
 35 char *version(void)
 36 {
 37   const char data[]=__DATE__;
 38   const char tempo[]=__TIME__;
 39   const char nomes[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
 40   char omes[4];
 41   int ano, mes, dia, hora, min, seg;
 42 
 43   if(strcmp(sversion,"9999.9999.20150710.045535"))
 44     return sversion;
 45 
 46   if(strlen(data)!=11||strlen(tempo)!=8)
 47     return NULL;
 48 
 49   sscanf(data, "%s %d %d", omes, &dia, &ano);
 50   sscanf(tempo, "%d:%d:%d", &hora, &min, &seg);
 51   mes=(strstr(nomes, omes)-nomes)/3+1;
 52   sprintf(sversion,"%d.%d.%04d%02d%02d.%02d%02d%02d", MAJOR, MINOR, ano, mes, dia, hora, min, seg);
 53 
 54   return sversion;
 55 }
 56 #endif

Lütfen dizgenin MAJOR<=9999 ve MINOR<=9999 ile sınırlı olduğunu unutmayın. Tabii ki, umarım asla taşmayacak bu yüksek değeri belirlerim. Ancak double kullanmak hala daha iyidir (artı, tamamen otomatiktir, MAJOR ve MINOR'yi elle ayarlamaya gerek yoktur).

Şimdi, yukarıdaki program biraz fazla. İşlevi tamamen kaldırmak daha iyidir ve VERSION makrosunun -DVERSION tarafından doğrudan GCC komut satırına (veya otomatik olarak ekleyen bir takma ad ekleyeceğiniz) ya da önerilen çözümü bu sürece dahil etmeyi garanti etmektir. makefile içine.

İşte makefile kullanıyorum:


MakeFile kaynağı:

  1   MAJOR = 3
  2   MINOR = 33
  3   BUILD = $(Shell date +"%Y%m%d.%H%M%S")
  4   VERSION = "\"$(MAJOR).$(MINOR).$(BUILD)\""
  5   CC = gcc
  6   CFLAGS = -Wall -Wextra -g -O0 -ansi -pedantic-errors
  7   CPPFLAGS = -DVERSION=$(VERSION)
  8   LDLIBS =
  9   
 10    %.x : %.c
 11          $(CC) $(CFLAGS) $(CPPFLAGS) $(LDLIBS) $^ -o [email protected]

DOUBLE ile daha iyi bir sürüm

Şimdi size "sizin" tercih ettiğiniz çözümü sundum, işte benim çözümüm:

(A) makefile veya (b) gcc ile doğrudan derleyin:

(a) MakeFile:

   VERSION = $(Shell date +"%g%m%d.%H%M%S")
   CC = gcc
   CFLAGS = -Wall -Wextra -g -O0 -ansi -pedantic-errors 
   CPPFLAGS = -DVERSION=$(VERSION)
   LDLIBS =
   %.x : %.c
         $(CC) $(CFLAGS) $(CPPFLAGS) $(LDLIBS) $^ -o [email protected]

(b) Veya basit bir bash komutu:

 $ gcc program.c -o program.x -Wall -Wextra -g -O0 -ansi -pedantic-errors -DVERSION=$(date +"%g%m%d.%H%M%S")

Kaynak kodu (çift versiyon):

#ifndef VERSION
  #define VERSION version()
#endif

double version(void);

int main(void)
{
  printf("VERSION%s: '%13.6f'\n", (FUNC_VERSION?"()":""), VERSION);
  return 0;
}

double version(void)
{
  const char data[]=__DATE__;
  const char tempo[]=__TIME__;
  const char nomes[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  char omes[4];
  int ano, mes, dia, hora, min, seg;
  char sversion[]="130910.001339";
  double fv;

  if(strlen(data)!=11||strlen(tempo)!=8)
    return -1.0;

  sscanf(data, "%s %d %d", omes, &dia, &ano);
  sscanf(tempo, "%d:%d:%d", &hora, &min, &seg);
  mes=(strstr(nomes, omes)-nomes)/3+1;
  sprintf(sversion,"%04d%02d%02d.%02d%02d%02d", ano, mes, dia, hora, min, seg);
  fv=atof(sversion);

  return fv;
}

Not: Bu çift fonksiyon sadece makro SÜRÜMÜ tanımlamayı unuttuğunuzda vardır. makefile kullanıyorsanız veya bir alias gcc gcc -DVERSION=$(date +"%g%m%d.%H%M%S") ayarladıysanız, bu işlevi tamamen silebilirsiniz.


İşte bu. Sürüm kontrolünüzü ayarlamanın ve bir daha asla endişelenmenize gerek yok!

3
Dr Beco

Günün 10'dan küçük olması durumunda, yalnızca '' (boşluk) yerine geçmek isteyen herkes için kullanın:

#define BUILD_DATE (char const[]) { __DATE__[0], __DATE__[1], __DATE__[2], __DATE__[3], (__DATE__[4] == ' ' ?  '0' : __DATE__[4]), __DATE__[5], __DATE__[6], __DATE__[7], __DATE__[8], __DATE__[9], __DATE__[10], __DATE__[11] }

Çıktı: Eylül 06 2019

0
hueman

o çok basit....

[dosyada]

==== 1 ==================================

OBJS = .... \

version.o <<== add to your obj lists

==== 2 ==================================

DATE = $ (Kabuk tarihi + 'char szVersionStr [20] = "% Y-% m-% d% H:% M:% S";') << == ekleyin 

tümü: sürüm $ (ProgramID) << == ilk önce sürüm ekleme

sürüm: << == ekle

echo '$(DATE)' > version.c  <== add ( create version.c file)

[programda]

===== 3 ==============

dış karakter szVersionStr [20];

[kullanarak]

=== 4 ====

printf( "Version: %s\n", szVersionStr );
0
turningeagle