سؤال

وأنا باستخدام دول مجلس التعاون الخليجي. __FILE__ إرجاع الملف المصدر الحالي المسار واسم كامل: /path/to/file.cpp. هل هناك طريقة للحصول على مجرد file.cpp اسم الملف (بدون مساره) في وقت الترجمة؟ هل من الممكن أن تفعل هذا بطريقة المحمولة؟ يمكن أن يطبق القالب البرمجة الفوقية إلى سلاسل؟

وأنا أستخدم هذا في ماكرو تسجيل الخطأ. أنا حقا لا أريد المسار الكامل بلدي المصدر تشق طريقها إلى الملف القابل للتنفيذ.

هل كانت مفيدة؟

المحلول

إذا كنت تستخدم برنامج جعل، يجب أن تكون قادرة على ل Munge اسم الملف مسبقا وتمريرها كما ماكرو لدول مجلس التعاون الخليجي لاستخدامها في البرنامج.

في MAKEFILE الخاص بك، قم بتغيير السطر:

file.o: file.c
    gcc -c -o file.o src/file.c

إلى:

file.o: src/file.c
    gcc "-D__MYFILE__=\"`basename $<`\"" -c -o file.o src/file.c

وهذا سوف يسمح لك لاستخدام __MYFILE__ في التعليمات البرمجية بدلا من __FILE__.

واستخدام basename من الملف المصدر ($ <) يعني أنه يمكنك استخدامه في قواعد المعممة مثل ".c.o".

وتوضح التعليمة البرمجية التالية كيف يعمل.

MAKEFILE الملف:

mainprog: main.o makefile
    gcc -o mainprog main.o

main.o: src/main.c makefile
    gcc "-D__MYFILE__=\"`basename $<`\"" -c -o main.o src/main.c

الملف SRC / main.c:

#include <stdio.h>

int main (int argc, char *argv[]) {
    printf ("file = %s\n", __MYFILE__);
    return 0;
}

تشغيل من قذيفة:

pax@pax-desktop:~$ mainprog
file = main.c
pax@pax-desktop:~$

لاحظ خط "ملف =" الذي يحتوي فقط على basename الملف، وليس dirname.

نصائح أخرى

والنظر في هذا الكود بسيط:

#include <stdio.h>
int main(void)
{
    puts(__FILE__);
    return(0);
}

في سولاريس، مع دول مجلس التعاون الخليجي 4.3.1، إذا كنت تجميع هذه باستخدام:

gcc -o x x.c && ./x

والإخراج هو "x.c" إذا كنت ترجمة باستخدام:

gcc -o x $PWD/x.c && ./x

وبعد ذلك __FILE__ الخرائط إلى المسار الكامل ( '/work1/jleffler/tmp/x.c'). إذا كنت ترجمة باستخدام:

gcc -o x ../tmp/x.c && ./x

وبعد ذلك __FILE__ الخرائط إلى '../tmp/x.c ".

وهكذا، في الأساس، __FILE__ هو مسار الملف المصدر. إذا كنت بناء مع الاسم الذي تريد أن تراه في وجوه، كل شيء على ما يرام.

وإذا كان هذا هو المستحيل (لأي سبب كان)، ثم سيكون لديك للوصول الى الحلول المقترحة من قبل أشخاص آخرين.

وأنا لا أعرف من وسيلة مباشرة. هل يمكن استخدام:

#line 1 "filename.c"

في الجزء العلوي من الملف المصدر إلى تعيين قيمة __FILE__، لكنني لست متأكدا من أن ذلك أفضل بكثير من الصعب الترميز ذلك. أو فقط باستخدام رقم تعريف لإنشاء ماكرو الخاص بك.

وثمة خيار آخر قد يكون لتمرير اسم من ماكيفيلي باستخدام -D و$ (شل basename $ <)

وتحرير: إذا كنت تستخدم رقم تعريف أو خيار -D، يجب إنشاء الاسم الجديد الخاص بك، وليس محاولة لإعادة تعريف __FILE__

وماذا لديك خطأ تسجيل ماكرو تفعل؟ وأود أن نفترض في مرحلة ما الماكرو يدعو في نهاية المطاف وظيفة من نوع ما من أجل القيام على تسجيل، لماذا لا يكون دعا قطاع ظيفة قبالة مكون مسار في وقت التشغيل؟

#define LOG(message) _log(__FILE__, message)

void _log(file, message)
{
  #ifndef DEBUG
  strippath(file); // in some suitable way
  #endif

  cerr << "Log: " << file << ": " << message; // or whatever
}

ومنذ كنت الموسومة CMake، وهنا حل أنيق لإضافة إلى CMakeLists.txt الخاص بك: (نسخ من http://www.cmake.org/pipermail/cmake/ 2011-ديسمبر / 048281.html ). (ملاحظة: بعض المجمعين لا تدعم COMPILE_DEFINITIONS لكل ملف لكنها تعمل مع دول مجلس التعاون الخليجي)

set(SRCS a/a.cpp b/b.cpp c/c.cpp d/d.cpp)

foreach(f IN LISTS SRCS)
 get_filename_component(b ${f} NAME)
 set_source_files_properties(${f} PROPERTIES
  COMPILE_DEFINITIONS "MYSRCNAME=${b}")
endforeach()

add_executable(foo ${SRCS})

ملحوظة: للحصول على طلبي وكنت بحاجة للهروب من سلسلة اسم مثل هذا:

COMPILE_DEFINITIONS "MYSRCNAME=\"${b}\"")

وأخذ فكرة من Glomek، فإنه يمكن أن يكون آليا مثل هذا:

المصدر ملف x.c

#line 1 MY_FILE_NAME
#include <stdio.h>

int main(void)
{
    puts(__FILE__);
    return(0);
}

وخط تجميع (حذار من علامات الاقتباس المفردة خارج التنصيص):

gcc -DMY_FILE_NAME='"abcd.c"' -o x x.c

والإخراج هو "abcd.c".

ويمكنك تعيين __FILE__ إلى سلسلة، ومن ثم استدعاء _splitpath () أن يمزق قطع للخروج منه. هذا قد يكون حلا ويندوز / MSVC فقط، وبصراحة أنا لا أعرف.

وأنا أعلم أنك تبحث عن حل وقت الترجمة وهذا هو الحل وقت التشغيل، لكنني أحسب منذ كنت تستخدم اسم الملف للقيام (ويفترض وقت التشغيل) تسجيل الخطأ، وهذا يمكن أن يكون وسيلة بسيطة ومباشرة لتحصل على ما تحتاج إليه.

ويمكنك أن تأخذ __FILE__ وتجريدها من جزء من المسار الذي لا يريد (برمجيا). إذا basedir يلبي احتياجاتك، ثم غرامة. خلاف ذلك، والحصول على مصدر دير الجذر من نظام البناء الخاص بك، وينبغي أن تكون قابلة للتنفيذ بقية.

وحصلت للتو على نفس القضية. العثور على دقة مختلفة، بس كنت تشاركه:

في ملف رأس تضمينها في كافة الملفات الأخرى بلدي:

static char * file_bname = NULL;
#define __STRIPPED_FILE__   (file_bname ?: (file_bname = basename(__FILE__)))

وهذا الأمل هو مفيد لشخص آخر أيضا:)

ويمكن أن يتم ذلك فقط برمجيا.

وربما هذا هو مفيد ...

filename = __FILE__
len  = strlen(filename)

char *temp = &filename[len -1]
while(*temp!= filename)
    if(*temp == '\') break;

ومن السهل مع cmake.

وDefineRelativeFilePaths.cmake

function (cmake_define_relative_file_paths SOURCES)
  foreach (SOURCE IN LISTS SOURCES)
    file (
      RELATIVE_PATH RELATIVE_SOURCE_PATH
      ${PROJECT_SOURCE_DIR} ${SOURCE}
    )

    set_source_files_properties (
      ${SOURCE} PROPERTIES
      COMPILE_DEFINITIONS __RELATIVE_FILE_PATH__="${RELATIVE_SOURCE_PATH}"
    )
  endforeach ()
endfunction ()

وفي مكان ما في CMakeLists.txt

set (SOURCES ${SOURCES}
  "${CMAKE_CURRENT_SOURCE_DIR}/common.c"
  "${CMAKE_CURRENT_SOURCE_DIR}/main.c"
)

include (DefineRelativeFilePaths)
cmake_define_relative_file_paths ("${SOURCES}")

وcmake .. && make clean && make VERBOSE=1

cc ... -D__RELATIVE_FILE_PATH__="src/main.c" ... -c src/main.c

وهذا كل شيء. الآن يمكنك جعل رسائل سجل جميلة.

#define ..._LOG_HEADER(target) \
  fprintf(target, "%s %s:%u - ", __func__, __RELATIVE_FILE_PATH__, __LINE__);
<اقتباس فقرة>   

وظائفها SRC / main.c: 22 - خطأي

وPS فمن الأفضل أن نقوم declear في config.h.in -> config.h

#ifndef __RELATIVE_FILE_PATH__
#define __RELATIVE_FILE_PATH__ __FILE__
#endif

وهكذا اللنت بك wan't توفر الأمطار من الأخطاء.

هل يمكن استخدام:

bool IsDebugBuild()
{
    return !NDEBUG;
}

وأو، هل يمكن استخدام NDEBUG في ماكرو لتشغيل / إيقاف تلك مسارات الملفات.

scroll top