]> git.cworth.org Git - apitrace/blob - cli/cli_resources.cpp
cli: use $LIB to handle multilib automagically on glibc
[apitrace] / cli / cli_resources.cpp
1 /*********************************************************************
2  *
3  * Copyright 2011 Intel Corporation
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use, copy,
10  * modify, merge, publish, distribute, sublicense, and/or sell copies
11  * of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  *
26  *********************************************************************/
27
28
29 #include <iostream>
30
31 #include "os_string.hpp"
32
33 #include "cli_resources.hpp"
34
35 #ifdef __GLIBC__
36
37 #include <dlfcn.h>
38
39 static bool
40 tryLib(const os::String &path, bool verbose)
41 {
42     void *handle = dlopen(path.str(), RTLD_LAZY);
43     bool exists = (handle != NULL);
44     if (verbose) {
45         if (exists) {
46             std::cerr << "info: found " << path.str() << "\n";
47         } else {
48             std::cerr << "info: did not find " << dlerror() << "\n";
49         }
50     }
51     if (exists)
52         dlclose(handle);
53     return exists;
54 }
55 #endif
56
57 static bool
58 tryPath(const os::String &path, bool verbose)
59 {
60     bool exists = path.exists();
61     if (verbose) {
62         std::cerr << "info: " << (exists ? "found" : "did not find") << " " << path.str() << "\n";
63     }
64     return exists;
65 }
66
67 os::String
68 findProgram(const char *programFilename, bool verbose)
69 {
70     os::String programPath;
71
72     os::String processDir = os::getProcessName();
73     processDir.trimFilename();
74
75     programPath = processDir;
76     programPath.join(programFilename);
77     if (tryPath(programPath, verbose)) {
78         return programPath;
79     }
80
81 #ifndef _WIN32
82     // Try absolute install directory
83     programPath = APITRACE_PROGRAMS_INSTALL_DIR;
84     programPath.join(programFilename);
85     if (tryPath(programPath, verbose)) {
86         return programPath;
87     }
88 #endif
89
90     return "";
91 }
92
93 os::String
94 findWrapper(const char *wrapperFilename, bool verbose)
95 {
96     os::String wrapperPath;
97
98     os::String processDir = os::getProcessName();
99     processDir.trimFilename();
100
101     // Try relative build directory
102     // XXX: Just make build and install directory layout match
103     wrapperPath = processDir;
104 #if defined(APITRACE_CONFIGURATION_SUBDIR)
105     // Go from `Debug\apitrace.exe` to `wrappers\Debug\foo.dll` on MSVC builds.
106     wrapperPath.join("..");
107     wrapperPath.join("wrappers");
108     wrapperPath.join(APITRACE_CONFIGURATION_SUBDIR);
109 #else
110     wrapperPath.join("wrappers");
111 #endif
112     wrapperPath.join(wrapperFilename);
113     if (tryPath(wrapperPath, verbose)) {
114         return wrapperPath;
115     }
116
117 #ifdef __GLIBC__
118     // We want to take advantage of $LIB dynamic string token expansion in
119     // glibc dynamic linker to handle multilib layout for us
120     wrapperPath = processDir;
121     wrapperPath.join("../$LIB/apitrace/wrappers");
122     wrapperPath.join(wrapperFilename);
123     if (tryLib(wrapperPath, verbose)) {
124         return wrapperPath;
125     }
126 #endif
127
128     // Try relative install directory
129     wrapperPath = processDir;
130 #if defined(_WIN32)
131     wrapperPath.join("..\\lib\\wrappers");
132 #elif defined(__APPLE__)
133     wrapperPath.join("../lib/wrappers");
134 #else
135     wrapperPath.join("../lib/apitrace/wrappers");
136 #endif
137     wrapperPath.join(wrapperFilename);
138     if (tryPath(wrapperPath, verbose)) {
139         return wrapperPath;
140     }
141
142 #ifndef _WIN32
143     // Try absolute install directory
144     wrapperPath = APITRACE_WRAPPERS_INSTALL_DIR;
145     wrapperPath.join(wrapperFilename);
146     if (tryPath(wrapperPath, verbose)) {
147         return wrapperPath;
148     }
149 #endif
150
151     return "";
152 }
153
154 os::String
155 findScript(const char *scriptFilename, bool verbose)
156 {
157     os::String scriptPath;
158
159     os::String processDir = os::getProcessName();
160     processDir.trimFilename();
161
162     // Try relative build directory
163     // XXX: Just make build and install directory layout match
164 #if defined(APITRACE_SOURCE_DIR)
165     scriptPath = APITRACE_SOURCE_DIR;
166     scriptPath.join("scripts");
167     scriptPath.join(scriptFilename);
168     if (tryPath(scriptPath, verbose)) {
169         return scriptPath;
170     }
171 #endif
172
173     // Try relative install directory
174     scriptPath = processDir;
175 #if defined(_WIN32)
176     scriptPath.join("..\\lib\\scripts");
177 #elif defined(__APPLE__)
178     scriptPath.join("../lib/scripts");
179 #else
180     scriptPath.join("../lib/apitrace/scripts");
181 #endif
182     scriptPath.join(scriptFilename);
183     if (tryPath(scriptPath, verbose)) {
184         return scriptPath;
185     }
186
187 #ifndef _WIN32
188     // Try absolute install directory
189     scriptPath = APITRACE_SCRIPTS_INSTALL_DIR;
190     scriptPath.join(scriptFilename);
191     if (tryPath(scriptPath, verbose)) {
192         return scriptPath;
193     }
194 #endif
195
196     std::cerr << "error: cannot find " << scriptFilename << " script\n";
197
198     return "";
199 }