Better default resource dir heuristics: use system resource dir with system clang and relative path to resource dir with bundled clang (#137)

This commit is contained in:
Chen 2017-12-15 06:35:21 +08:00 committed by Fangrui Song
parent d8b47ebdd4
commit f3f7bc26cd
5 changed files with 58 additions and 11 deletions

View File

@ -86,12 +86,15 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
// Ensure there is a resource directory. // Ensure there is a resource directory.
if (config->resourceDirectory.empty()) { if (config->resourceDirectory.empty()) {
config->resourceDirectory = GetWorkingDirectory(); std::string defaultResourceDirectory = std::string(DEFAULT_RESOURCE_DIRECTORY);
#if defined(_WIN32) if (defaultResourceDirectory.find("..") != std::string::npos) {
config->resourceDirectory += std::string("../../clang_resource_dir/"); std::string executablePath = GetExecutablePath();
#else size_t pos = executablePath.find_last_of('/');
config->resourceDirectory += std::string("../clang_resource_dir/"); config->resourceDirectory = executablePath.substr(0, pos+1);
#endif config->resourceDirectory += defaultResourceDirectory;
} else {
config->resourceDirectory = defaultResourceDirectory;
}
} }
config->resourceDirectory = NormalizePath(config->resourceDirectory); config->resourceDirectory = NormalizePath(config->resourceDirectory);
LOG_S(INFO) << "Using -resource-dir=" << config->resourceDirectory; LOG_S(INFO) << "Using -resource-dir=" << config->resourceDirectory;

View File

@ -31,6 +31,7 @@ std::unique_ptr<PlatformSharedMemory> CreatePlatformSharedMemory(
void PlatformInit(); void PlatformInit();
std::string GetExecutablePath();
std::string GetWorkingDirectory(); std::string GetWorkingDirectory();
std::string NormalizePath(const std::string& path); std::string NormalizePath(const std::string& path);
// Creates a directory at |path|. Creates directories recursively if needed. // Creates a directory at |path|. Creates directories recursively if needed.

View File

@ -210,6 +210,27 @@ std::unique_ptr<PlatformSharedMemory> CreatePlatformSharedMemory(
void PlatformInit() {} void PlatformInit() {}
#ifdef __APPLE__
extern "C" int _NSGetExecutablePath(char* buf,uint32_t* bufsize);
#endif
// See https://stackoverflow.com/questions/143174/how-do-i-get-the-directory-that-a-program-is-running-from
std::string GetExecutablePath() {
#ifndef __APPLE__
char buffer[PATH_MAX+1] = {0};
readlink("/proc/self/exe", buffer, PATH_MAX);
return std::string(buffer);
#else
uint32_t size = 0;
_NSGetExecutablePath(nullptr, &size);
char *buffer = new char[size];
_NSGetExecutablePath(buffer, &size);
std::string result(buffer);
delete[] buffer;
return result;
#endif
}
std::string GetWorkingDirectory() { std::string GetWorkingDirectory() {
char result[FILENAME_MAX]; char result[FILENAME_MAX];
if (!getcwd(result, sizeof(result))) if (!getcwd(result, sizeof(result)))

View File

@ -127,6 +127,13 @@ void PlatformInit() {
_setmode(_fileno(stdin), O_BINARY); _setmode(_fileno(stdin), O_BINARY);
} }
// See https://stackoverflow.com/questions/143174/how-do-i-get-the-directory-that-a-program-is-running-from
std::string GetExecutablePath() {
char result[MAX_PATH] = {0};
GetModuleFileName(NULL, result, MAX_PATH);
return std::string(result);
}
// See http://stackoverflow.com/a/19535628 // See http://stackoverflow.com/a/19535628
std::string GetWorkingDirectory() { std::string GetWorkingDirectory() {
char result[MAX_PATH]; char result[MAX_PATH];

23
wscript
View File

@ -10,6 +10,7 @@ import os.path
import string import string
import subprocess import subprocess
import sys import sys
import re
VERSION = '0.0.1' VERSION = '0.0.1'
APPNAME = 'cquery' APPNAME = 'cquery'
@ -198,11 +199,25 @@ def build(bld):
lib.append('pthread') lib.append('pthread')
clang_tarball_name = None clang_tarball_name = None
# Fallback for windows
default_resource_directory = os.path.join(os.getcwd(), 'resource_dir')
if bld.env['use_system_clang']: if bld.env['use_system_clang']:
rpath = [] rpath = []
output = subprocess.check_output(['clang', '-###', '-xc', '/dev/null'], stderr=subprocess.STDOUT)
match = re.search(r'"-resource-dir" "([^"]*)"', output, re.M | re.I)
if match:
default_resource_directory = match.group(1)
else:
print("Failed to found system clang resource directory. Falling back.")
elif sys.platform.startswith('freebsd') or sys.platform.startswith('linux'): elif sys.platform.startswith('freebsd') or sys.platform.startswith('linux'):
clang_tarball_name = os.path.basename(os.path.dirname(bld.env['LIBPATH_clang'][0])) clang_tarball_name = os.path.basename(os.path.dirname(bld.env['LIBPATH_clang'][0]))
rpath = '$ORIGIN/../lib/' + clang_tarball_name + '/lib' rpath = '$ORIGIN/../lib/' + clang_tarball_name + '/lib'
default_resource_directory = '../lib/' + clang_tarball_name + '/resource-dir'
elif sys.platform == 'darwin':
clang_tarball_name = os.path.basename(os.path.dirname(bld.env['LIBPATH_clang'][0]))
rpath = '@loader_path/../lib/' + clang_tarball_name + '/lib'
default_resource_directory = '../lib/' + clang_tarball_name + '/resource-dir'
else: else:
rpath = bld.env['LIBPATH_clang'] rpath = bld.env['LIBPATH_clang']
bld.program( bld.program(
@ -216,15 +231,15 @@ def build(bld):
'third_party/rapidjson/include/', 'third_party/rapidjson/include/',
'third_party/sparsehash/src/', 'third_party/sparsehash/src/',
'third_party/sparsepp/'], 'third_party/sparsepp/'],
defines=['LOGURU_WITH_STREAMS=1'], defines=['LOGURU_WITH_STREAMS=1',
'DEFAULT_RESOURCE_DIRECTORY="' + default_resource_directory + '"'],
lib=lib, lib=lib,
rpath=rpath, rpath=rpath,
target='bin/cquery') target='bin/cquery')
if bld.cmd == 'install':
if clang_tarball_name is not None: if clang_tarball_name is not None:
bld.install_files('${PREFIX}/lib/' + clang_tarball_name + '/lib', bld.path.get_bld().ant_glob('lib/clang+llvm*/lib/libclang.so.[4-9]')) bld.install_files('${PREFIX}/lib/' + clang_tarball_name + '/lib', bld.path.get_bld().ant_glob('lib/' + clang_tarball_name + '/lib/libclang.(dylib|so.[4-9])', quiet=True))
bld.install_files('${PREFIX}/lib/' + clang_tarball_name + '/resource-dir/include', bld.path.get_bld().ant_glob('lib/clang+llvm*/lib/clang/[4-9]*/include/*')) bld.install_files('${PREFIX}/lib/' + clang_tarball_name + '/resource-dir/include', bld.path.get_bld().ant_glob('lib/' + clang_tarball_name + '/lib/clang/[4-9]*/include/*', quiet=True))
#bld.shlib(source='a.cpp', target='mylib', vnum='9.8.7') #bld.shlib(source='a.cpp', target='mylib', vnum='9.8.7')
#bld.shlib(source='a.cpp', target='mylib2', vnum='9.8.7', cnum='9.8') #bld.shlib(source='a.cpp', target='mylib2', vnum='9.8.7', cnum='9.8')