argv[0]
현재 프로세스를 로드하게 만든 쉘 명령을 참조합니다. getcwd()
현재 작업 디렉토리로 돌아갑니다. 이 정보를 통해 프로그램의 바이너리 실행 파일에 대한 절대 경로를 구성할 수 있습니까? 프로그램이 cd
처음 로드된 이후 이미 완료된 경우에는 작동하지 않기를 바랍니다.
답변1
프로그래밍 언어 인터프리터 내에서 다음 코드를 사용하여 자체 경로를 가져옵니다.
Linux, Windows(Cygwin 포함), Mac 및 Solaris용 특수 코드가 있습니다.
#if __APPLE__
#include <mach-o/dyld.h>
#endif
#if __linux__
static val get_self_path(void)
{
char self[PATH_MAX] = { 0 };
int nchar = readlink("/proc/self/exe", self, sizeof self);
if (nchar < 0 || nchar >= convert(int, sizeof self))
return nil;
return string_utf8(self);
}
#elif HAVE_WINDOWS_H
static val get_self_path(void)
{
wchar_t self[MAX_PATH] = { 0 };
DWORD nchar;
SetLastError(0);
nchar = GetModuleFileNameW(NULL, self, MAX_PATH);
if (nchar == 0 ||
(nchar == MAX_PATH &&
((GetLastError() == ERROR_INSUFFICIENT_BUFFER) ||
(self[MAX_PATH - 1] != 0))))
return nil;
return string(self);
}
#elif __APPLE__
static val get_self_path(void)
{
char self[PATH_MAX] = { 0 };
uint32_t size = sizeof self;
if (_NSGetExecutablePath(self, &size) != 0)
return nil;
return string_utf8(self);
}
#elif HAVE_GETEXECNAME
static val get_self_path(void)
{
val execname = string_utf8(getexecname());
if (car(execname) == chr('/'))
return execname;
return scat3(getcwd_wrap(), chr('/'), execname);
}
#else
static val get_self_path(void)
{
char self[PATH_MAX];
if (argv[0] && realpath(argv[0], self))
return string_utf8(self);
return lit(HARD_INSTALLATION_PATH);
}
#endif
유형 val
, 기호 및 nil
함수는 인터프리터 내부에 있습니다. 그냥 추상 캐스팅 매크로입니다. 물론 일부 헤더 파일도 필요합니다.string
string_utf8
convert
readlink
realpath
이 getexecname
기능은 Solaris의 것입니다. 어떤 이유로 절대 경로를 얻으려면 현재 디렉터리를 붙여넣어야 하는 상대 경로를 처리하는 상황에서 코딩하고 있는 것 같습니다.
대체 전략은 argv[0]
from 을 main
사용할 수 있는 경우 realpath
이를 호출하고 실행하는 것입니다. 이를 사용할 수 없는 경우 argv[0]
변수의 하드코딩된 설치 경로를 사용합니다 Makefile
. 예를 들어, 프로그램이 로 설치된 경우 /usr/bin/foo
레시피 Makefile
는 이를 컴파일러 명령줄에 로 삽입합니다 -DHARD_INSTALLATION_PATH=/usr/bin/foo
. 물론 이는 프로그램이 빌드 경로에 설치된 경우에만 해당됩니다.
답변2
Linux에서는 심볼릭 링크를 사용할 수 있습니다/proc/self/exe
$ ls -l /proc/self/exe
lrwxrwxrwx 1 rudi users 0 2016-10-18 16:20 /proc/self/exe -> /usr/bin/ls