2010-09-23 13 views
16

प्राप्त करने के लिए सीएमके का उपयोग करें सीएमके के साथ मैं Subversion_WC_INFO का उपयोग करके svn संशोधन प्राप्त कर सकता हूं। हालांकि, यह केवल कॉन्फ़िगरेशन समय पर होता है - प्रत्येक बाद के मेक इस कैश किए गए संशोधन का उपयोग करेंगे।बिल्ड-टाइम svn संशोधन

मैं बिल्डिंग समय (यानि, हर बार चलाने के लिए) पर svn संशोधन प्राप्त करना चाहता हूं। मैं यह कैसे कर सकता हूँ?

उत्तर

29

यह होने की तुलना में ऐसा करने के लिए दर्द का अधिक दर्द है। आप विवर्तन से संस्करण जानकारी निकालने के लिए निर्माण समय पर एक प्रोग्राम चला सकते हैं। सीएमके स्वयं को अपनी स्क्रिप्टिंग भाषा का उपयोग करके इस कार्यक्रम के रूप में इस्तेमाल किया जा सकता है। आप -पी कमांड लाइन ध्वज का उपयोग कर किसी भी सीएमके स्क्रिप्ट को चला सकते हैं। कोड का टुकड़ा यह करने के लिए (फ़ाइल getsvn.cmake में रखा करने के लिए जा सकती है) किया जाएगा:

# the FindSubversion.cmake module is part of the standard distribution 
include(FindSubversion) 
# extract working copy information for SOURCE_DIR into MY_XXX variables 
Subversion_WC_INFO(${SOURCE_DIR} MY) 
# write a file with the SVNVERSION define 
file(WRITE svnversion.h.txt "#define SVNVERSION ${MY_WC_REVISION}\n") 
# copy the file to the final header only if the version changes 
# reduces needless rebuilds 
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different 
         svnversion.h.txt svnversion.h) 

यह तोड़फोड़ संशोधन जानकारी निकाल लेता है और यह एक हेडर फाइल करने के लिए लिखता है। यह हेडर फ़ाइल केवल तभी अपडेट की जाती है जब हर समय recompiling से बचने के लिए आवश्यक है। आपके प्रोग्राम में, आप उस हेडर फ़ाइल को SVNVERSION परिभाषित करने के लिए शामिल करेंगे।

# boilerplate 
cmake_minimum_required(VERSION 2.8) 
project(testsvn) 

# the test executable 
add_executable(test main.c ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h) 

# include the output directory, where the svnversion.h file is generated 
include_directories(${CMAKE_CURRENT_BINARY_DIR}) 

# a custom target that is always built 
add_custom_target(svnheader ALL 
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/svnheader.h) 

# creates svnheader.h using cmake script 
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/svnheader.h 
    COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} 
         -P ${CMAKE_CURRENT_SOURCE_DIR}/getsvn.cmake) 

# svnversion.h is a generated file 
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/svnversion.h 
    PROPERTIES GENERATED TRUE 
    HEADER_FILE_ONLY TRUE) 

# explicitly say that the executable depends on the svnheader 
add_dependencies(test svnheader) 

आप add_custom_target और add_custom_command का उपयोग करने के बाद से वहाँ svnheader.h फाइल करने के लिए कोई आदानों हैं की जरूरत है, यह "प्रकट होता है:

CMakeLists.txt फ़ाइल है कि आप स्क्रिप्ट चलाने के लिए की आवश्यकता होगी कुछ इस तरह होगा कहीं से "सेमेक तक। मैंने पहले से ही getvn.cmake फ़ाइल में अनावश्यक पुनर्निर्माण के मुद्दे से निपटाया है, इसलिए "svnheader" लक्ष्य का पुनर्निर्माण मूल रूप से एक नो-ऑप है यदि उपversण संशोधन नहीं बदला गया है।

अंत में

, एक उदाहरण main.c फ़ाइल:

#include "svnversion.h" 

int main(int argc, const char *argv[]) 
{ 
    printf("%d\n", SVNVERSION); 
    return 0; 
} 
+0

बहुत बढ़िया जवाब:

# a custom target that is always built add_custom_target(svnheader ALL DEPENDS svn_header) # svn_header is nothing more than a unique string # creates svnheader.h using cmake script add_custom_command(OUTPUT svn_header ${CMAKE_CURRENT_BINARY_DIR}/svnheader.h COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/getsvn.cmake) 

इसके अलावा, किसी Git का उपयोग करना चाहता है, cmake स्क्रिप्ट के लिए इस का उपयोग । पता नहीं था कि निर्माण समय पर सेमेक स्क्रिप्ट को निष्पादित किया जा सकता है। – paleozogt

+0

यह वास्तव में ऐसा नहीं करता है जो कोई अपेक्षा करेगा। जब 'मेक' कहा जाता है तो यह स्वचालित रूप से 'revision.h' को अपडेट नहीं करता है। आपके समाधान को थोड़ा संशोधित करना होगा - मैं इसे एक उत्तर में डालूंगा, इसलिए मैं कोड टैग का उपयोग कर सकता हूं ... – janitor048

+0

@janitor बस इसे फिर से परीक्षण किया, जैसा कि मैंने मूल रूप से किया था, और यह निश्चित रूप से अपेक्षित रूप से काम करता है। आपको प्रत्येक कॉल पर "जेनरेटिंग svnheader.h" संदेश भी मिलता है, जिसे आप अपने संशोधित संस्करण में नहीं करते हैं। साथ ही, 'revision.h' कोड में नहीं है, तो हो सकता है कि आपके पास कॉपी-पेस्ट त्रुटि हो? – richq

1

मुझे ऐसा करने के लिए किसी भी सीएमके-विशिष्ट कार्यक्षमता के बारे में पता नहीं है, लेकिन आपके निर्माण चरणों में से एक के रूप में स्वयं को करना आसान है। एक स्क्रिप्ट से svnversion चलाने के लिए और इसके उत्पादन, या (आसान) TortoiseSVN के subwcrev कार्यक्रम चलाने (जो भी अन्य ऑपरेटिंग सिस्टम पर वापस पोर्ट कर दिया गया है, तो यह विंडोज-विशिष्ट नहीं है) को पार्स।

0

मैं वास्तव में एक ही बात के लिए देख रहा हूँ और मैंने पाया इस: howto-use-cmake-with-cc-projects यह बहुत सरल लगता है, लेकिन अगर यह RQ के रूप में के रूप में कुशल है मैं सोच रहा हूँ जवाब।

+0

इस दृष्टिकोण के साथ "समस्या" यह है कि यह केवल कॉन्फ़िगरेशन समय पर संशोधन जानकारी अपडेट करता है, यानी 'cmake' जारी करते समय। डेल्टा को बाद में 'मेक' द्वारा निर्मित करते समय अपडेट नहीं किया जाता है। – janitor048

2

मैंने पाया कि इस सवाल का जवाब richq द्वारा दिए गए वास्तव में है नहीं है एक उम्मीद क्या होगा - अर्थात् यह स्वचालित रूप से फ़ाइल svnversion.h (जिसमें SVN संशोधन की जानकारी संग्रहीत किया जाता है) अपडेट नहीं होता केवल निर्माण (लेकिन को विन्यस्त नहीं) स्रोत , यानी जब make पर कॉल किया जाता है।

यहां उनकी प्रक्रिया का थोड़ा संशोधित संस्करण है जो आवश्यक व्यवहार प्रदान करना चाहिए। मूल समाधान के लिए क्रेडिट निश्चित रूप से richq के लिए जाता है।

उनकी getsvn.cmake स्क्रिप्ट अपरिवर्तित रहता है, यहाँ यह (टिप्पणियों और स्पष्टीकरण के लिए अपने जवाब देखने)

INCLUDE(FindSubversion) 
Subversion_WC_INFO(${SOURCE_DIR} MY) 
FILE(WRITE svnversion.h.txt "#define SVNVERSION ${MY_WC_REVISION}\n") 
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different 
     svnversion.h.txt svnversion.h) 

अब चाल एक अलग हस्ताक्षर के साथ ADD_CUSTOM_COMMAND उपयोग करने के लिए (CMake Documentation देखें) पूर्णता के लिए के लिए है, अर्थात् लक्ष्य निर्दिष्ट करना जिसके साथ कमांड को जोड़ा जाना चाहिए। इसके बाद लक्ष्य को हर बार निष्पादित किया जाता है - एक साथ ADD_CUSTOM_TARGET से खाली लक्ष्य के साथ जिसे हमेशा पुराना माना जाता है, यह वांछित व्यवहार देता है।यहां बताया गया है CMakeLists.txt की तरह (आधारित फिर स्क्रिप्ट पर richq द्वारा) लग सकता है:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 
PROJECT(testsvn) 

# the test executable 
ADD_EXECUTABLE(test main.c) 

# include the output directory, where the svnversion.h file is generated 
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) 

# a custom target that is always built 
ADD_CUSTOM_TARGET(revisiontag ALL) 

# creates svnversion.h using cmake script 
ADD_CUSTOM_COMMAND(TARGET revisiontag COMMAND ${CMAKE_COMMAND} 
    -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} 
    -P ${CMAKE_CURRENT_SOURCE_DIR}/getsvn.cmake) 

# explicitly say that the executable depends on custom target 
add_dependencies(test revisiontag) 

अब स्क्रिप्ट getsvn.cmake हर बार लक्ष्य revisiontag बनाया गया है, जो हर बार make जारी किया जाता है इसका मतलब है निष्पादित किया जाता है। getsvn.cmake में FILE(..) के साथ लाइन को टिप्पणी करके परीक्षण करें और मैन्युअल रूप से svnversion.h.txt संपादित करें।

+0

धन्यवाद - कि revisiontag लक्ष्य ने मुझे यह काम करने में मदद की। –

8

मुझे विश्वास है कि मुझे @ janitor048 समस्या @ richq के उत्तर के साथ मिली है। दुर्भाग्यवश, मेरे पास उनके उत्तर पर टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है - शायद कोई और कॉपी और पेस्ट कर सकता है।

@richq कस्टम आदेश और कस्टम लक्ष्य दोनों का उपयोग करता है। सेमेक को मनाने के लिए कस्टम कमांड आवश्यक है कि हेडर बनाया जाएगा, अन्यथा सेमेक स्क्रिप्ट को कस्टम लक्ष्य के लिए कमांड के रूप में निष्पादित किया जा सकता है। जबकि एक कस्टम लक्ष्य हमेशा निष्पादित किया जाएगा, एक कस्टम कमांड नहीं होगा अगर इसकी आउटपुट फ़ाइल पहले से मौजूद है।

वर्कअराउंड कस्टम लक्ष्य पर एक फर्जी निर्भरता (एक काल्पनिक फ़ाइल) जोड़ना है, और cmake को बताएं कि कस्टम कमांड उस फ़ाइल को बनाता है। यह सुनिश्चित करने के लिए पर्याप्त है कि कस्टम कमांड हमेशा निष्पादित होता है। सौभाग्य से, cmake वास्तव में यह जांच नहीं करता है कि यह फ़ाइल बनाई गई है या नहीं।

richq है:

# a custom target that is always built 
add_custom_target(svnheader ALL 
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/svnheader.h) 

# creates svnheader.h using cmake script 
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/svnheader.h 
    COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} 
         -P ${CMAKE_CURRENT_SOURCE_DIR}/getsvn.cmake) 

यह मेरे लिए काम करता है:

#create a pretty commit id using git 
#uses 'git describe --tags', so tags are required in the repo 
#create a tag with 'git tag <name>' and 'git push --tags' 

find_package(Git) 
if(GIT_FOUND) 
    execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags RESULT_VARIABLE res_var OUTPUT_VARIABLE GIT_COM_ID) 
    if(NOT ${res_var} EQUAL 0) 
     set(GIT_COMMIT_ID "git commit id unknown") 
     message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.") 
    endif() 
    string(REPLACE "\n" "" GIT_COMMIT_ID ${GIT_COM_ID}) 
else() 
    set(GIT_COMMIT_ID "unknown (git not found!)") 
    message(WARNING "Git not found. Build will not contain git revision info.") 
endif() 

set(vstring "//version_string.hpp - written by cmake. changes will be lost!\n" 
      "const char * VERSION_STRING = \"${GIT_COMMIT_ID}\"\;\n") 

file(WRITE version_string.hpp.txt ${vstring}) 
# copy the file to the final header only if the version changes 
# reduces needless rebuilds 
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different 
         version_string.hpp.txt ${CMAKE_CURRENT_BINARY_DIR}/version_string.hpp) 
संबंधित मुद्दे