~ubuntu-branches/ubuntu/vivid/soundscaperenderer/vivid

« back to all changes in this revision

Viewing changes to data/MacOSX/dylibbundler/src/Dependency.cpp

  • Committer: Package Import Robot
  • Author(s): IOhannes m zmölnig (Debian/GNU)
  • Date: 2014-05-08 16:58:09 UTC
  • Revision ID: package-import@ubuntu.com-20140508165809-7tz9dhu5pvo5wy25
Tags: upstream-0.4.1~dfsg
Import upstream version 0.4.1~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 This program is free software; you can redistribute it and/or modify
 
3
 it under the terms of the GNU General Public License as published by
 
4
 the Free Software Foundation; either version 2 of the License, or
 
5
 (at your option) any later version.
 
6
 
 
7
 This program is distributed in the hope that it will be useful,
 
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 GNU General Public License for more details.
 
11
 
 
12
 You should have received a copy of the GNU General Public License along
 
13
 with this program; if not, write to the Free Software Foundation, Inc.,
 
14
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
15
 */
 
16
 
 
17
#include "Dependency.h"
 
18
#include <iostream>
 
19
#include <cstdlib>
 
20
#include <sys/param.h>
 
21
#include "Utils.h"
 
22
#include "Settings.h"
 
23
 
 
24
#include <stdlib.h>
 
25
#include <sstream>
 
26
#include <vector>
 
27
 
 
28
std::string stripPrefix(std::string in)
 
29
{
 
30
    return in.substr(in.rfind("/")+1);
 
31
}
 
32
 
 
33
//the pathes to search for dylibs, store it globally to parse the environment variables only once
 
34
std::vector<std::string> pathes;
 
35
 
 
36
//initialize the dylib search pathes
 
37
void initSearchPathes(){
 
38
    //Check the same pathes the system would search for dylibs
 
39
    std::string searchPathes;
 
40
    char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH");
 
41
    if( dyldLibPath!=0 )
 
42
        searchPathes = dyldLibPath;
 
43
    dyldLibPath = std::getenv("DYLD_FALLBACK_FRAMEWORK_PATH");
 
44
    if (dyldLibPath != 0)
 
45
    {
 
46
        if (!searchPathes.empty() && searchPathes[ searchPathes.size()-1 ] != ':') searchPathes += ":"; 
 
47
        searchPathes += dyldLibPath;
 
48
    }
 
49
    dyldLibPath = std::getenv("DYLD_FALLBACK_LIBRARY_PATH");
 
50
    if (dyldLibPath!=0 )
 
51
    {
 
52
        if (!searchPathes.empty() && searchPathes[ searchPathes.size()-1 ] != ':') searchPathes += ":"; 
 
53
        searchPathes += dyldLibPath;
 
54
    }
 
55
    if (!searchPathes.empty())
 
56
    {
 
57
        std::stringstream ss(searchPathes);
 
58
        std::string item;
 
59
        while(std::getline(ss, item, ':'))
 
60
        {
 
61
            if (item[ item.size()-1 ] != '/') item += "/";
 
62
            pathes.push_back(item);
 
63
        }
 
64
    }
 
65
}
 
66
 
 
67
// if some libs are missing prefixes, this will be set to true
 
68
// more stuff will then be necessary to do
 
69
bool missing_prefixes = false;
 
70
 
 
71
Dependency::Dependency(std::string path)
 
72
{
 
73
    // check if given path is a symlink
 
74
    std::string cmd = "readlink -n " + path;
 
75
    const bool is_symlink = system( (cmd+" > /dev/null").c_str())==0;
 
76
    if (is_symlink)
 
77
    {
 
78
        char original_file_buffer[PATH_MAX];
 
79
        std::string original_file;
 
80
        
 
81
        if (not realpath(path.c_str(), original_file_buffer))
 
82
        {
 
83
            std::cerr << "\n/!\\ WARNING : Cannot resolve symlink '" << path.c_str() << "'" << std::endl;
 
84
            original_file = path;
 
85
        }
 
86
        else
 
87
        {
 
88
            original_file = original_file_buffer;
 
89
        }
 
90
        //original_file = original_file.substr(0, original_file.find("\n") );
 
91
        
 
92
        filename = stripPrefix(original_file);
 
93
        prefix = path.substr(0, path.rfind("/")+1);
 
94
        addSymlink(path);
 
95
    }
 
96
    else
 
97
    {
 
98
        filename = stripPrefix(path);
 
99
        prefix = path.substr(0, path.rfind("/")+1);
 
100
    }
 
101
    
 
102
    //check if the lib is in a known location
 
103
    if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/";
 
104
    if( prefix.empty() || !fileExists( prefix+filename ) )
 
105
    {
 
106
        //the pathes contains at least /usr/lib so if it is empty we have not initilazed it
 
107
        if( pathes.empty() ) initSearchPathes();
 
108
        
 
109
        //check if file is contained in one of the pathes
 
110
        for( size_t i=0; i<pathes.size(); ++i)
 
111
        {
 
112
            if (fileExists( pathes[i]+filename ))
 
113
            {
 
114
                std::cout << "FOUND " << filename << " in " << pathes[i] << std::endl;
 
115
                prefix = pathes[i];
 
116
                missing_prefixes = true; //the prefix was missing
 
117
                break;
 
118
            }
 
119
        }
 
120
    }
 
121
    
 
122
    //If the location is still unknown, ask the user for search path
 
123
    if( prefix.empty() || !fileExists( prefix+filename ) )
 
124
    {
 
125
        std::cerr << "\n/!\\ WARNING : Library " << filename << " has an incomplete name (location unknown)" << std::endl;
 
126
        missing_prefixes = true;
 
127
        
 
128
        while (true)
 
129
        {
 
130
            std::cout << "Please specify now where this library can be found (or write 'quit' to abort): ";  fflush(stdout);
 
131
            
 
132
            char buffer[128];
 
133
            std::cin >> buffer;
 
134
            prefix = buffer;
 
135
            std::cout << std::endl;
 
136
            
 
137
            if(prefix.compare("quit")==0) exit(1);
 
138
            
 
139
            if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/";
 
140
            
 
141
            if( !fileExists( prefix+filename ) )
 
142
            {
 
143
                std::cerr << (prefix+filename) << " does not exist. Try again" << std::endl;
 
144
                continue;
 
145
            }
 
146
            else
 
147
            {
 
148
                pathes.push_back( prefix );
 
149
                std::cerr << (prefix+filename) << " was found. /!\\MANUALLY CHECK THE EXECUTABLE WITH 'otool -L', DYLIBBUNDLDER MAY NOT HANDLE CORRECTLY THIS UNSTANDARD/ILL-FORMED DEPENDENCY" << std::endl;
 
150
                break;
 
151
            }
 
152
        }
 
153
    }
 
154
    
 
155
    //new_name  = filename.substr(0, filename.find(".")) + ".dylib";
 
156
    new_name = filename;
 
157
}
 
158
 
 
159
void Dependency::print()
 
160
{
 
161
    std::cout << std::endl;
 
162
    std::cout << " * " << filename.c_str() << " from " << prefix.c_str() << std::endl;
 
163
    
 
164
    const int symamount = symlinks.size();
 
165
    for(int n=0; n<symamount; n++)
 
166
        std::cout << "     symlink --> " << symlinks[n].c_str() << std::endl;;
 
167
}
 
168
 
 
169
std::string Dependency::getInstallPath()
 
170
{
 
171
    return Settings::destFolder() + new_name;
 
172
}
 
173
std::string Dependency::getInnerPath()
 
174
{
 
175
    return Settings::inside_lib_path() + new_name;
 
176
}
 
177
 
 
178
 
 
179
void Dependency::addSymlink(std::string s){ symlinks.push_back(stripPrefix(s)); }
 
180
 
 
181
// comapres the given Dependency with this one. If both refer to the same file,
 
182
// it returns true and merges both entries into one.
 
183
bool Dependency::mergeIfSameAs(Dependency& dep2)
 
184
{
 
185
    if(dep2.getOriginalFileName().compare(filename) == 0)
 
186
    {
 
187
        const int samount = dep2.getSymlinkAmount();
 
188
        for(int n=0; n<samount; n++)
 
189
            addSymlink( dep2.getSymlink(n) ); // FIXME - there may be duplicate symlinks
 
190
        return true;
 
191
    }
 
192
    return false;
 
193
}
 
194
 
 
195
void Dependency::copyYourself()
 
196
{
 
197
    copyFile(getOriginalPath(), getInstallPath());
 
198
    
 
199
    // Fix the lib's inner name
 
200
    std::string command = std::string("install_name_tool -id ") + getInnerPath() + " " + getInstallPath();
 
201
    if( systemp( command ) != 0 )
 
202
    {
 
203
        std::cerr << "\n\nError : An error occured while trying to change identity of library " << getInstallPath() << std::endl;
 
204
        exit(1);
 
205
    }
 
206
}
 
207
 
 
208
void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
 
209
{
 
210
    // for main lib file
 
211
    std::string command = std::string("install_name_tool -change ") +
 
212
    getOriginalPath() + " " + getInnerPath() + " " + file_to_fix;
 
213
    
 
214
    if( systemp( command ) != 0 )
 
215
    {
 
216
        std::cerr << "\n\nError : An error occured while trying to fix depencies of " << file_to_fix << std::endl;
 
217
        exit(1);
 
218
    }
 
219
    
 
220
    // for symlinks
 
221
    const int symamount = symlinks.size();
 
222
    for(int n=0; n<symamount; n++)
 
223
    {
 
224
        std::string command = std::string("install_name_tool -change ") +
 
225
        prefix+symlinks[n] + " " + getInnerPath() + " " + file_to_fix;
 
226
        
 
227
        if( systemp( command ) != 0 )
 
228
        {
 
229
            std::cerr << "\n\nError : An error occured while trying to fix depencies of " << file_to_fix << std::endl;
 
230
            exit(1);
 
231
        }
 
232
    }
 
233
    
 
234
    
 
235
    // FIXME - hackish
 
236
    if(missing_prefixes)
 
237
    {
 
238
        // for main lib file
 
239
        std::string command = std::string("install_name_tool -change ") +
 
240
        filename + " " + getInnerPath() + " " + file_to_fix;
 
241
        
 
242
        if( systemp( command ) != 0 )
 
243
        {
 
244
            std::cerr << "\n\nError : An error occured while trying to fix depencies of " << file_to_fix << std::endl;
 
245
            exit(1);
 
246
        }
 
247
        
 
248
        // for symlinks
 
249
        const int symamount = symlinks.size();
 
250
        for(int n=0; n<symamount; n++)
 
251
        {
 
252
            std::string command = std::string("install_name_tool -change ") +
 
253
            symlinks[n] + " " + getInnerPath() + " " + file_to_fix;
 
254
            
 
255
            if( systemp( command ) != 0 )
 
256
            {
 
257
                std::cerr << "\n\nError : An error occured while trying to fix depencies of " << file_to_fix << std::endl;
 
258
                exit(1);
 
259
            }
 
260
        }//next
 
261
    }// end if(missing_prefixes)
 
262
}