source: CLRX/CLRadeonExtender/trunk/utils/Utilities.cpp @ 3220

Last change on this file since 3220 was 3220, checked in by matszpk, 3 years ago

CLRadeonExtender: empty line.

File size: 21.5 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#if defined(HAVE_LINUX) || defined(HAVE_BSD)
22#include <dlfcn.h>
23#endif
24#ifdef HAVE_WINDOWS
25#include <direct.h>
26#include <windows.h>
27#include <shlobj.h>
28#else
29#include <pwd.h>
30#include <unistd.h>
31#include <sys/stat.h>
32#include <sys/wait.h>
33#endif
34#include <fstream>
35#include <fcntl.h>
36#include <sys/stat.h>
37#include <mutex>
38#include <cerrno>
39#include <cstring>
40#include <string>
41#include <climits>
42#define __UTILITIES_MODULE__ 1
43#include <CLRX/utils/Utilities.h>
44
45using namespace CLRX;
46
47Exception::Exception(const std::string& _message) : message(_message)
48{ }
49
50const char* Exception::what() const noexcept
51{
52    return message.c_str();
53}
54
55ParseException::ParseException(const std::string& message) : Exception(message)
56{ }
57
58ParseException::ParseException(LineNo lineNo, const std::string& message)
59{
60    char buf[32];
61    itocstrCStyle(lineNo, buf, 32);
62    this->message = buf;
63    this->message += ": ";
64    this->message += message;
65}
66
67ParseException::ParseException(LineNo lineNo, ColNo charNo, const std::string& message)
68{
69    char buf[32];
70    itocstrCStyle(lineNo, buf, 32);
71    this->message = buf;
72    this->message += ": ";
73    itocstrCStyle(charNo, buf, 32);
74    this->message += buf;
75    this->message += ": ";
76    this->message += message;
77}
78
79std::mutex CLRX::DynLibrary::mutex;
80
81DynLibrary::DynLibrary() : handle(nullptr)
82{ }
83
84DynLibrary::DynLibrary(const char* filename, Flags flags) : handle(nullptr)
85{
86    load(filename, flags);
87}
88
89DynLibrary::~DynLibrary()
90{
91    unload();
92}
93
94void DynLibrary::load(const char* filename, Flags flags)
95{
96    std::lock_guard<std::mutex> lock(mutex);
97#if defined(HAVE_LINUX) || defined(HAVE_BSD)
98    dlerror(); // clear old errors
99    int outFlags = (flags & DYNLIB_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL;
100    if ((flags & DYNLIB_MODE1_MASK) == DYNLIB_LAZY)
101        outFlags |= RTLD_LAZY;
102    if ((flags & DYNLIB_MODE1_MASK) == DYNLIB_NOW)
103        outFlags |= RTLD_NOW;
104    handle = dlopen(filename, outFlags);
105    if (handle == nullptr)
106        throw Exception(dlerror());
107#endif
108#ifdef HAVE_WINDOWS
109    handle = (void*)LoadLibrary(filename);
110    if (handle == nullptr)
111        throw Exception("DynLibrary::load failed");
112#endif
113}
114
115void DynLibrary::unload()
116{
117    std::lock_guard<std::mutex> lock(mutex);
118    if (handle != nullptr)
119    {
120#if defined(HAVE_LINUX) || defined(HAVE_BSD)
121        dlerror(); // clear old errors
122        if (dlclose(handle)) // if closing failed
123            throw Exception(dlerror());
124#endif
125#ifdef HAVE_WINDOWS
126        if (!FreeLibrary((HMODULE)handle))
127            throw Exception("DynLibrary::unload failed");
128#endif
129    }
130    handle = nullptr;
131}
132
133void* DynLibrary::getSymbol(const char* symbolName)
134{
135    if (handle == nullptr)
136        throw Exception("DynLibrary not loaded!");
137   
138    std::lock_guard<std::mutex> lock(mutex);
139    void* symbol = nullptr;
140#if defined(HAVE_LINUX) || defined(HAVE_BSD)
141    dlerror(); // clear old errors
142    symbol = dlsym(handle, symbolName);
143    const char* error = dlerror();
144    if (symbol == nullptr && error != nullptr)
145        throw Exception(error);
146#endif
147#ifdef HAVE_WINDOWS
148    symbol = (void*)GetProcAddress((HMODULE)handle, symbolName);
149    if (symbol==nullptr)
150        throw Exception("DynLibrary::getSymbol failed");
151#endif
152    return symbol;
153}
154
155template
156cxuchar CLRX::parseEnvVariable<cxuchar>(const char* envVar,
157                const cxuchar& defaultValue);
158
159template
160cxchar CLRX::parseEnvVariable<cxchar>(const char* envVar,
161              const cxchar& defaultValue);
162
163
164template
165cxuint CLRX::parseEnvVariable<cxuint>(const char* envVar,
166               const cxuint& defaultValue);
167
168template
169cxint CLRX::parseEnvVariable<cxint>(const char* envVar,
170               const cxint& defaultValue);
171
172template
173cxushort CLRX::parseEnvVariable<cxushort>(const char* envVar,
174               const cxushort& defaultValue);
175
176template
177cxshort CLRX::parseEnvVariable<cxshort>(const char* envVar,
178               const cxshort& defaultValue);
179
180template
181cxulong CLRX::parseEnvVariable<cxulong>(const char* envVar,
182               const cxulong& defaultValue);
183
184template
185cxlong CLRX::parseEnvVariable<cxlong>(const char* envVar,
186               const cxlong& defaultValue);
187
188template
189cxullong CLRX::parseEnvVariable<cxullong>(const char* envVar,
190               const cxullong& defaultValue);
191
192template
193cxllong CLRX::parseEnvVariable<cxllong>(const char* envVar,
194               const cxllong& defaultValue);
195
196template
197float CLRX::parseEnvVariable<float>(const char* envVar,
198            const float& defaultValue);
199
200template
201double CLRX::parseEnvVariable<double>(const char* envVar,
202              const double& defaultValue);
203
204
205namespace CLRX
206{
207template<>
208std::string parseEnvVariable<std::string>(const char* envVar,
209              const std::string& defaultValue)
210{
211    const char* var = getenv(envVar);
212    if (var == nullptr)
213        return defaultValue;
214    return var;
215}
216
217template<>
218bool parseEnvVariable<bool>(const char* envVar, const bool& defaultValue)
219{
220    const char* var = getenv(envVar);
221    if (var == nullptr)
222        return defaultValue;
223   
224    // skip spaces
225    for (; *var == ' ' || *var == '\t' || *var == '\r'; var++);
226   
227    for (const char* v: { "1", "true", "t", "on", "yes", "y"})
228        if (::strncasecmp(var, v, ::strlen(v)) == 0)
229            return true;
230    return false; // false
231}
232};
233
234template
235std::string CLRX::parseEnvVariable<std::string>(const char* envVar,
236              const std::string& defaultValue);
237
238template
239bool CLRX::parseEnvVariable<bool>(const char* envVar, const bool& defaultValue);
240
241/// escape char names witout '\'
242static const char cstyleEscapesTable[32] =
243{
244    0, 0, 0, 0, 0, 0, 0, 'a', 'b', 't', 'n', 'v', 'f', 'r', 0, 0,
245    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
246};
247
248std::string CLRX::escapeStringCStyle(size_t strSize, const char* str)
249{
250    std::string out;
251    out.reserve(strSize);
252    bool notFullOctalEscape = false;
253    for (size_t i = 0; i < strSize; i++)
254    {
255        const cxbyte c = str[i];
256        if (c < 0x20 || c > 0x7e || (notFullOctalEscape && c >= 0x30 && c <= 0x37))
257        {
258            if (c < 0x20 && cstyleEscapesTable[c] != 0)
259            {
260                out.push_back('\\');
261                out.push_back(cstyleEscapesTable[c]);
262                notFullOctalEscape = false;
263            }
264            else // otherwise
265            {
266                out.push_back('\\');
267                if ((c>>6) != 0)
268                    out.push_back('0'+(c>>6));
269                if ((c>>3) != 0)
270                    out.push_back('0'+((c>>3)&7));
271                out.push_back('0'+(c&7));
272                // if next character can change octal escape
273                notFullOctalEscape = ((c>>6) == 0);
274            }
275        }
276        else  if (c == '\"')
277        {   // backslash
278            out.push_back('\\');
279            out.push_back('\"');
280            notFullOctalEscape = false;
281        }
282        else  if (c == '\'')
283        {   // backslash
284            out.push_back('\\');
285            out.push_back('\'');
286            notFullOctalEscape = false;
287        }
288        else  if (c == '\\')
289        {   // backslash
290            out.push_back('\\');
291            out.push_back('\\');
292            notFullOctalEscape = false;
293        }
294        else // otherwise normal character
295        {
296            out.push_back(c);
297            notFullOctalEscape = false;
298        }
299    }
300    return out;
301}
302
303size_t CLRX::escapeStringCStyle(size_t strSize, const char* str,
304                 size_t outMaxSize, char* outStr, size_t& outSize)
305{
306    size_t i = 0, d = 0;
307    bool notFullOctalEscape = false;
308    for (i = 0; i < strSize; i++)
309    {
310        const cxbyte c = str[i];
311        if (c < 0x20 || c > 0x7e || (notFullOctalEscape && c >= 0x30 && c <= 0x37))
312        {
313            if (c < 0x20 && cstyleEscapesTable[c] != 0)
314            {
315                if (d+2 >= outMaxSize)
316                    break; // end
317                outStr[d++] = '\\';
318                outStr[d++] = cstyleEscapesTable[c];
319                notFullOctalEscape = false;
320            }
321            else // otherwise
322            {
323                if (d + 2 + ((c>>3) != 0) + ((c>>6) != 0) >= outMaxSize)
324                    break; // end
325                outStr[d++] = '\\';
326                if ((c>>6) != 0)
327                    outStr[d++] = '0'+(c>>6);
328                if ((c>>3) != 0)
329                    outStr[d++] = '0'+((c>>3)&7);
330                outStr[d++] = '0'+(c&7);
331                // if next character can change octal escape
332                notFullOctalEscape = ((c>>6) == 0);
333            }
334        }
335        else  if (c == '\"')
336        {   // backslash
337            if (d+2 >= outMaxSize)
338                break; // end
339            outStr[d++] = '\\';
340            outStr[d++] = '\"';
341            notFullOctalEscape = false;
342        }
343        else  if (c == '\'')
344        {   // backslash
345            if (d+2 >= outMaxSize)
346                break; // end
347            outStr[d++] = '\\';
348            outStr[d++] = '\'';
349            notFullOctalEscape = false;
350        }
351        else  if (c == '\\')
352        {   // backslash
353            if (d+2 >= outMaxSize)
354                break; // end
355            outStr[d++] = '\\';
356            outStr[d++] = '\\';
357            notFullOctalEscape = false;
358        }
359        else // otherwise normal character
360        {
361            if (d+1 >= outMaxSize)
362                break; // end
363            outStr[d++] = c;
364            notFullOctalEscape = false;
365        }
366    }
367    outStr[d] = 0;
368    outSize = d;
369    return i;
370}
371
372bool CLRX::isDirectory(const char* path)
373{
374    struct stat stBuf;
375    errno = 0;
376    if (::stat(path, &stBuf) != 0)
377    {
378        if (errno == ENOENT)
379            throw Exception("File or directory doesn't exists");
380        else if (errno == EACCES)
381            throw Exception("Access to file or directory is not permitted");
382        else
383            throw Exception("Can't determine whether path refers to directory");
384    }
385#ifdef HAVE_WINDOWS
386    return (_S_IFDIR&stBuf.st_mode)!=0;
387#else
388    return S_ISDIR(stBuf.st_mode);
389#endif
390}
391
392/// returns true if file exists
393bool CLRX::isFileExists(const char* path)
394{
395#ifdef HAVE_WINDOWS
396    return GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES ||
397            GetLastError()!=ERROR_FILE_NOT_FOUND;
398#else
399    return ::access(path, F_OK)==0;
400#endif
401}
402
403Array<cxbyte> CLRX::loadDataFromFile(const char* filename)
404{
405    uint64_t size;
406    if (isDirectory(filename))
407        throw Exception("This is directory!");
408   
409    std::ifstream ifs(filename, std::ios::binary);
410    if (!ifs)
411        throw Exception("Can't open file");
412    ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit);
413   
414    bool seekingIsWorking = true;
415    try
416    { ifs.seekg(0, std::ios::end); /* to end of file */ }
417    catch(const std::exception& ex)
418    {   /* oh, no! this is not regular file */
419        seekingIsWorking = false;
420        ifs.clear();
421    }
422    Array<cxbyte> buf;
423    ifs.exceptions(std::ifstream::badbit); // ignore failbit for read
424    if (seekingIsWorking)
425    {   // just read whole file to memory
426        size = ifs.tellg();
427        if (size > SIZE_MAX)
428            throw Exception("File is too big to load");
429        ifs.seekg(0, std::ios::beg);
430        buf.resize(size);
431        ifs.read((char*)buf.data(), size);
432        if (ifs.gcount() != std::streamsize(size))
433            throw Exception("Can't read whole file");
434    }
435    else
436    {   /* growing, growing... */
437        size_t prevBufSize = 0;
438        size_t readBufSize = 256;
439        buf.resize(readBufSize);
440        while(true)
441        {
442            ifs.read((char*)(buf.data()+prevBufSize), readBufSize-prevBufSize);
443            const size_t readed = ifs.gcount();
444            if (readed < readBufSize-prevBufSize)
445            {   /* final resize */
446                buf.resize(prevBufSize + readed);
447                break;
448            }
449            prevBufSize = readBufSize;
450            readBufSize = prevBufSize+(prevBufSize>>1);
451            buf.resize(readBufSize);
452        }
453    }
454    return buf;
455}
456
457void CLRX::filesystemPath(char* path)
458{
459    while (*path != 0)  // change to native dir separator
460        if (*path == CLRX_ALT_DIR_SEP)
461            *path = CLRX_NATIVE_DIR_SEP;
462}
463
464void CLRX::filesystemPath(std::string& path)
465{
466    for (char& c: path)
467        if (c == CLRX_ALT_DIR_SEP)
468            c = CLRX_NATIVE_DIR_SEP;
469}
470
471std::string CLRX::joinPaths(const std::string& path1, const std::string& path2)
472{
473    std::string outPath = path1;
474    if (path1.back() == CLRX_NATIVE_DIR_SEP)
475    {
476        if (path2.size() >= 1 && path2.front() == CLRX_NATIVE_DIR_SEP)
477            // skip first dir separator
478            outPath.append(path2.begin()+1, path2.end());
479        else
480            outPath += path2;
481    }
482    else
483    {
484        if (path2.size() >= 1 && path2.front() != CLRX_NATIVE_DIR_SEP)
485            outPath.push_back(CLRX_NATIVE_DIR_SEP); // add dir separator
486        outPath += path2;
487    }
488    return outPath;
489}
490
491uint64_t CLRX::getFileTimestamp(const char* filename)
492{
493    struct stat stBuf;
494    errno = 0;
495    if (::stat(filename, &stBuf) != 0)
496    {
497        if (errno == ENOENT)
498            throw Exception("File or directory doesn't exists");
499        else if (errno == EACCES)
500            throw Exception("Access to file or directory is not permitted");
501        else
502            throw Exception("Can't determine whether path refers to directory");
503    }
504#if _POSIX_C_SOURCE>=200800L
505    return stBuf.st_mtim.tv_sec*1000000000ULL + stBuf.st_mtim.tv_nsec;
506#else
507    return stBuf.st_mtime*1000000000ULL;
508#endif
509}
510
511std::string CLRX::getHomeDir()
512{
513#ifndef HAVE_WINDOWS
514    struct passwd pw;
515    long pwbufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
516    if (pwbufSize != -1)
517    {
518        struct passwd* pwres;
519        Array<char> pwbuf(pwbufSize);
520        if (getpwuid_r(getuid(), &pw, pwbuf.data(), pwbufSize, &pwres)==0 &&
521                pwres!=nullptr)
522            return std::string(pwres->pw_dir);
523    }
524#else
525    // requires Windows XP or Windows 2000
526    char path[MAX_PATH];
527    if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_PROFILE, nullptr, 0, path)))
528        return std::string(path);
529#endif
530    return "";
531}
532
533void CLRX::makeDir(const char* dirname)
534{
535    errno = 0;
536#ifdef HAVE_WINDOWS
537    int ret = _mkdir(dirname);
538#else
539    // warning this is not thread safe code! (umask)
540    int um = umask(0);
541    umask(um);
542    int ret = ::mkdir(dirname, 0777&~um);
543#endif
544    if (ret!=0)
545    {
546        if (errno == EEXIST)
547            throw Exception("Directory already exists");
548        else if (errno == ENOENT)
549            throw Exception("No such parent directory");
550        else if (errno == EACCES)
551            throw Exception("Access to parent directory is not permitted");
552        else
553            throw Exception("Can't create directory");
554    }
555}
556
557CLRX::Array<cxbyte> CLRX::runExecWithOutput(const char* program, const char** argv)
558{
559#ifndef HAVE_WINDOWS
560    Array<cxbyte> output;
561    errno = 0;
562    int pipefds[2];
563    if (::pipe(pipefds) < 0)
564        throw Exception("Can't create pipe");
565    int fret = fork();
566    if (fret == 0)
567    {   // children
568        if (::close(1)<0)
569            ::exit(-1);
570        if (::dup2(pipefds[1], 1)<0) // redirection to pipe
571            ::exit(-1);
572        ::close(pipefds[0]);
573        ::execvp(program, (char**)argv);
574        ::exit(-1); // not
575    }
576    else if (fret > 0)
577    {   // parent
578        ::close(pipefds[1]);
579        /* growing, growing... */
580        size_t prevBufSize = 0;
581        size_t readBufSize = 256;
582        output.resize(readBufSize);
583        try
584        {
585        while(true)
586        {
587            while (prevBufSize < readBufSize)
588            {
589                ssize_t ret = ::read(pipefds[0], output.data()+prevBufSize,
590                            readBufSize-prevBufSize);
591                if (ret < 0)
592                    throw Exception("Can't read output of running process");
593                prevBufSize += ret;
594                if (ret == 0)
595                    break;
596            }
597            if (prevBufSize < readBufSize)
598            {   /* final resize */
599                output.resize(prevBufSize);
600                break;
601            }
602            prevBufSize = readBufSize;
603            readBufSize = prevBufSize+(prevBufSize>>1);
604            output.resize(readBufSize);
605        }
606        }
607        catch(...)
608        {   // close on error
609            ::waitpid(fret, nullptr, 0);
610            ::close(pipefds[0]);
611            throw;
612        }
613        int status = 0;
614        ::waitpid(fret, &status, 0);
615        ::close(pipefds[0]);
616        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
617            throw Exception("Process exited abnormally");
618    }
619    else
620        throw Exception("Can't create new process");
621    return output;
622#else
623    throw Exception("Unsupported function");
624#endif
625}
626
627static std::string findFileByEnvPaths(const char* envName, const char* fileName)
628{
629    // find by path
630    const std::string paths = parseEnvVariable<std::string>(envName);
631    for (size_t i = 0; i != std::string::npos; )
632    {
633#ifndef HAVE_WINDOWS
634        size_t nexti = paths.find(':', i);
635#else
636        size_t nexti = paths.find(';', i);
637#endif
638        std::string path;
639        if (nexti != std::string::npos)
640        {   // next
641            path = paths.substr(i, nexti-i);
642            i = nexti+1;
643        }
644        else
645        {   // last
646            path = paths.substr(i);
647            i = std::string::npos;
648        }
649        if (path.empty())
650            continue; // skip empty path
651        std::string filePath = joinPaths(path, fileName);
652        if (isFileExists(filePath.c_str()))
653            return filePath;
654    }
655    return "";
656}
657
658static const char* libAmdOCLPaths[] =
659{
660#ifdef HAVE_LINUX
661#  ifdef HAVE_32BIT
662     "/usr/lib/i386-linux-gnu/amdgpu-pro",
663     "/opt/amdgpu-pro/lib/i386-linux-gnu",
664     "/opt/amdgpu-pro/lib32",
665     "/opt/amdgpu-pro/lib",
666     "/usr/lib/i386-linux-gnu",
667     "/usr/lib32",
668     "/usr/lib"
669#  else
670     "/usr/lib/x86_64-linux-gnu/amdgpu-pro",
671     "/opt/amdgpu-pro/lib/x86_64-linux-gnu",
672     "/usr/lib/x86_64-linux-gnu",
673     "/opt/amdgpu-pro/lib64",
674     "/opt/amdgpu-pro/lib",
675     "/usr/lib64",
676     "/usr/lib"
677#  endif
678#elif defined(HAVE_WINDOWS)
679     "c:\\Windows\\System32"
680#endif
681};
682
683std::string CLRX::findAmdOCL()
684{
685    std::string amdOclPath = parseEnvVariable<std::string>("CLRX_AMDOCL_PATH", "");
686    if (!amdOclPath.empty())
687    {
688        if (isFileExists(amdOclPath.c_str()))
689            return amdOclPath;
690    }
691    else
692    {
693#ifndef HAVE_WINDOWS
694        amdOclPath = findFileByEnvPaths("LD_LIBRARY_PATH", DEFAULT_AMDOCLNAME);
695        if (!amdOclPath.empty())
696            return amdOclPath;
697#endif
698        for (const char* libPath: libAmdOCLPaths)
699        {
700            amdOclPath = joinPaths(libPath, DEFAULT_AMDOCLNAME);
701            if (isFileExists(amdOclPath.c_str()))
702                return amdOclPath;
703        }
704#ifdef HAVE_WINDOWS
705        return findFileByEnvPaths("PATH", DEFAULT_AMDOCLNAME);
706#endif
707    }
708    return "";
709}
710
711#ifndef HAVE_WINDOWS
712static const char* libMesaOCLPaths[] =
713{
714#  ifdef HAVE_32BIT
715     "/usr/lib/i386-linux-gnu",
716     "/usr/lib32",
717     "/usr/lib"
718#  else
719     "/usr/lib/x86_64-linux-gnu",
720     "/usr/lib64",
721     "/usr/lib"
722#  endif
723};
724#endif
725
726std::string CLRX::findMesaOCL()
727{
728#ifndef HAVE_WINDOWS
729    std::string mesaOclPath = parseEnvVariable<std::string>("CLRX_MESAOCL_PATH", "");
730    if (!mesaOclPath.empty())
731    {
732        if (isFileExists(mesaOclPath.c_str()))
733            return mesaOclPath;
734    }
735    else
736    {
737        mesaOclPath = findFileByEnvPaths("LD_LIBRARY_PATH", "libMesaOpenCL.so.1");
738        if (!mesaOclPath.empty())
739            return mesaOclPath;
740        for (const char* libPath: libMesaOCLPaths)
741        {
742            mesaOclPath = joinPaths(libPath, "libMesaOpenCL.so.1");
743            if (isFileExists(mesaOclPath.c_str()))
744                return mesaOclPath;
745        }
746#ifdef HAVE_64BIT
747        if (isFileExists("/usr/lib64/OpenCL/vendors/mesa/libOpenCL.so"))
748            return "/usr/lib64/OpenCL/vendors/mesa/libOpenCL.so";
749        if (isFileExists("/usr/lib/OpenCL/vendors/mesa/libOpenCL.so"))
750            return "/usr/lib/OpenCL/vendors/mesa/libOpenCL.so";
751#else
752        if (isFileExists("/usr/lib32/OpenCL/vendors/mesa/libOpenCL.so"))
753            return "/usr/lib32/OpenCL/vendors/mesa/libOpenCL.so";
754        if (isFileExists("/usr/lib/OpenCL/vendors/mesa/libOpenCL.so"))
755            return "/usr/lib/OpenCL/vendors/mesa/libOpenCL.so";
756#endif
757    }
758#endif
759    return "";
760}
761
762std::string CLRX::findLLVMConfig()
763{
764    std::string llvmConfigPath = parseEnvVariable<std::string>("CLRX_LLVMCONFIG_PATH", "");
765    if (!llvmConfigPath.empty())
766    {
767        if (isFileExists(llvmConfigPath.c_str()))
768            return llvmConfigPath;
769        return "";
770    }
771    else
772    {
773        // find by path
774        llvmConfigPath = findFileByEnvPaths("PATH", "llvm-config");
775        if (!llvmConfigPath.empty())
776            return llvmConfigPath;
777#ifndef HAVE_WINDOWS
778        if (isFileExists("/usr/bin/llvm-config"))
779            return "/usr/bin/llvm-config";
780#endif
781    }
782    return "";
783}
Note: See TracBrowser for help on using the repository browser.