2
0

jlibtool.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <sys/stat.h>
  20. #include <sys/types.h>
  21. #include <sys/wait.h>
  22. #include <unistd.h>
  23. #include <dirent.h>
  24. #include <errno.h>
  25. #include <assert.h>
  26. #ifdef __EMX__
  27. # define SHELL_CMD "sh"
  28. # define GEN_EXPORTS "emxexp"
  29. # define DEF2IMPLIB_CMD "emximp"
  30. # define SHARE_SW "-Zdll -Zmtd"
  31. # define USE_OMF 1
  32. # define TRUNCATE_DLL_NAME
  33. # define DYNAMIC_LIB_EXT "dll"
  34. # define EXE_EXT ".exe"
  35. # if USE_OMF
  36. /* OMF is the native format under OS/2 */
  37. # define STATIC_LIB_EXT "lib"
  38. # define OBJECT_EXT "obj"
  39. # define LIBRARIAN "emxomfar"
  40. # define LIBRARIAN_OPTS "cr"
  41. # else
  42. /* but the alternative, a.out, can fork() which is sometimes necessary */
  43. # define STATIC_LIB_EXT "a"
  44. # define OBJECT_EXT "o"
  45. # define LIBRARIAN "ar"
  46. # define LIBRARIAN_OPTS "cr"
  47. # endif
  48. #endif
  49. #if defined(__APPLE__)
  50. # define SHELL_CMD "/bin/sh"
  51. # define DYNAMIC_LIB_EXT "dylib"
  52. # define MODULE_LIB_EXT "so"
  53. # define STATIC_LIB_EXT "a"
  54. # define OBJECT_EXT "o"
  55. # define LIBRARIAN "ar"
  56. # define LIBRARIAN_OPTS "cr"
  57. /* man libtool(1) documents ranlib option of -c. */
  58. # define RANLIB "ranlib"
  59. # define PIC_FLAG "-fPIC -fno-common"
  60. # define SHARED_OPTS "-dynamiclib"
  61. # define MODULE_OPTS "-bundle"
  62. # define DYNAMIC_LINK_OPTS "-flat_namespace -undefined suppress"
  63. # define dynamic_link_version_func darwin_dynamic_link_function
  64. # define DYNAMIC_INSTALL_NAME "-install_name"
  65. # define DYNAMIC_LINK_NO_INSTALL "-dylib_file"
  66. # define HAS_REALPATH
  67. /*-install_name /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
  68. # define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
  69. #endif
  70. #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
  71. # define SHELL_CMD "/bin/sh"
  72. # define DYNAMIC_LIB_EXT "so"
  73. # define MODULE_LIB_EXT "so"
  74. # define STATIC_LIB_EXT "a"
  75. # define OBJECT_EXT "o"
  76. # define LIBRARIAN "ar"
  77. # define LIBRARIAN_OPTS "cr"
  78. # define RANLIB "ranlib"
  79. # define PIC_FLAG "-fPIC"
  80. # define RPATH "-rpath"
  81. # define SHARED_OPTS "-shared"
  82. # define MODULE_OPTS "-shared"
  83. # define DYNAMIC_LINK_OPTS "-export-dynamic"
  84. # define LINKER_FLAG_PREFIX "-Wl,"
  85. # define ADD_MINUS_L
  86. # define LD_RUN_PATH "LD_RUN_PATH"
  87. # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
  88. #endif
  89. #if defined(sun)
  90. # define SHELL_CMD "/bin/sh"
  91. # define DYNAMIC_LIB_EXT "so"
  92. # define MODULE_LIB_EXT "so"
  93. # define STATIC_LIB_EXT "a"
  94. # define OBJECT_EXT "o"
  95. # define LIBRARIAN "ar"
  96. # define LIBRARIAN_OPTS "cr"
  97. # define RANLIB "ranlib"
  98. # define PIC_FLAG "-KPIC"
  99. # define RPATH "-R"
  100. # define SHARED_OPTS "-G"
  101. # define MODULE_OPTS "-G"
  102. # define DYNAMIC_LINK_OPTS ""
  103. # define LINKER_FLAG_NO_EQUALS
  104. # define ADD_MINUS_L
  105. # define HAS_REALPATH
  106. # define LD_RUN_PATH "LD_RUN_PATH"
  107. # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
  108. #endif
  109. #if defined(_OSD_POSIX)
  110. # define SHELL_CMD "/usr/bin/sh"
  111. # define DYNAMIC_LIB_EXT "so"
  112. # define MODULE_LIB_EXT "so"
  113. # define STATIC_LIB_EXT "a"
  114. # define OBJECT_EXT "o"
  115. # define LIBRARIAN "ar"
  116. # define LIBRARIAN_OPTS "cr"
  117. # define SHARED_OPTS "-G"
  118. # define MODULE_OPTS "-G"
  119. # define LINKER_FLAG_PREFIX "-Wl,"
  120. # define NEED_SNPRINTF
  121. #endif
  122. #if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
  123. # define SHELL_CMD "/usr/bin/sh"
  124. # define DYNAMIC_LIB_EXT "so"
  125. # define MODULE_LIB_EXT "so"
  126. # define STATIC_LIB_EXT "a"
  127. # define OBJECT_EXT "o"
  128. # define LIBRARIAN "ar"
  129. # define LIBRARIAN_OPTS "cr"
  130. # define RPATH "-Brpath"
  131. # define SHARED_OPTS "-G"
  132. # define MODULE_OPTS "-G"
  133. # define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym"
  134. # define LINKER_FLAG_PREFIX "-Wl,"
  135. # define NEED_SNPRINTF
  136. # define LD_RUN_PATH "LD_RUN_PATH"
  137. # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
  138. #endif
  139. #ifndef SHELL_CMD
  140. #error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
  141. #endif
  142. #ifdef NEED_SNPRINTF
  143. #include <stdarg.h>
  144. #endif
  145. #ifdef __EMX__
  146. #include <process.h>
  147. #endif
  148. #ifndef PATH_MAX
  149. #define PATH_MAX 1024
  150. #endif
  151. /* We want to say we are libtool 1.4 for shlibtool compatibility. */
  152. #define VERSION "1.4"
  153. enum tool_mode_t {
  154. mUnknown,
  155. mCompile,
  156. mLink,
  157. mInstall,
  158. };
  159. enum output_t {
  160. otGeneral,
  161. otObject,
  162. otProgram,
  163. otLibrary,
  164. otStaticLibraryOnly,
  165. otDynamicLibraryOnly,
  166. otModule,
  167. };
  168. enum pic_mode_e {
  169. pic_UNKNOWN,
  170. pic_PREFER,
  171. pic_AVOID,
  172. };
  173. enum lib_type {
  174. type_UNKNOWN,
  175. type_DYNAMIC_LIB,
  176. type_STATIC_LIB,
  177. type_MODULE_LIB,
  178. type_OBJECT,
  179. };
  180. typedef struct {
  181. const char **vals;
  182. int num;
  183. } count_chars;
  184. typedef struct {
  185. const char *normal;
  186. const char *install;
  187. } library_name;
  188. typedef struct {
  189. count_chars *normal;
  190. count_chars *install;
  191. count_chars *dependencies;
  192. } library_opts;
  193. typedef struct {
  194. int silent;
  195. int shared;
  196. int export_all;
  197. int dry_run;
  198. enum pic_mode_e pic_mode;
  199. int export_dynamic;
  200. int no_install;
  201. } options_t;
  202. typedef struct {
  203. enum tool_mode_t mode;
  204. enum output_t output;
  205. options_t options;
  206. char *output_name;
  207. char *fake_output_name;
  208. char *basename;
  209. const char *install_path;
  210. const char *compiler;
  211. const char *program;
  212. count_chars *program_opts;
  213. count_chars *arglist;
  214. count_chars *tmp_dirs;
  215. count_chars *obj_files;
  216. count_chars *dep_rpaths;
  217. count_chars *rpaths;
  218. library_name static_name;
  219. library_name shared_name;
  220. library_name module_name;
  221. library_opts static_opts;
  222. library_opts shared_opts;
  223. const char *version_info;
  224. } command_t;
  225. #ifdef RPATH
  226. void add_rpath(count_chars *cc, const char *path);
  227. #endif
  228. #if defined(NEED_SNPRINTF)
  229. /* Write at most n characters to the buffer in str, return the
  230. * number of chars written or -1 if the buffer would have been
  231. * overflowed.
  232. *
  233. * This is portable to any POSIX-compliant system has /dev/null
  234. */
  235. static FILE *f=NULL;
  236. static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
  237. {
  238. int res;
  239. if (f == NULL)
  240. f = fopen("/dev/null","w");
  241. if (f == NULL)
  242. return -1;
  243. setvbuf( f, str, _IOFBF, n );
  244. res = vfprintf( f, fmt, ap );
  245. if ( res > 0 && res < n ) {
  246. res = vsprintf( str, fmt, ap );
  247. }
  248. return res;
  249. }
  250. static int snprintf( char *str, size_t n, const char *fmt, ... )
  251. {
  252. va_list ap;
  253. int res;
  254. va_start( ap, fmt );
  255. res = vsnprintf( str, n, fmt, ap );
  256. va_end( ap );
  257. return res;
  258. }
  259. #endif
  260. void init_count_chars(count_chars *cc)
  261. {
  262. cc->vals = (const char**)malloc(PATH_MAX);
  263. cc->num = 0;
  264. }
  265. void clear_count_chars(count_chars *cc)
  266. {
  267. int i;
  268. for (i = 0; i < cc->num; i++) {
  269. cc->vals[i] = 0;
  270. }
  271. cc->num = 0;
  272. }
  273. void push_count_chars(count_chars *cc, const char *newval)
  274. {
  275. cc->vals[cc->num++] = newval;
  276. }
  277. void insert_count_chars(count_chars *cc, const char *newval, int position)
  278. {
  279. int i;
  280. for (i = cc->num; i > position; i--) {
  281. cc->vals[i] = cc->vals[i-1];
  282. }
  283. cc->vals[position] = newval;
  284. cc->num++;
  285. }
  286. void append_count_chars(count_chars *cc, count_chars *cctoadd)
  287. {
  288. int i;
  289. for (i = 0; i < cctoadd->num; i++) {
  290. if (cctoadd->vals[i]) {
  291. push_count_chars(cc, cctoadd->vals[i]);
  292. }
  293. }
  294. }
  295. const char *flatten_count_chars(count_chars *cc)
  296. {
  297. int i, size;
  298. char *newval;
  299. size = 0;
  300. for (i = 0; i < cc->num; i++) {
  301. if (cc->vals[i]) {
  302. size += strlen(cc->vals[i]) + 1;
  303. }
  304. }
  305. newval = (char*)malloc(size + 1);
  306. newval[0] = 0;
  307. for (i = 0; i < cc->num; i++) {
  308. if (cc->vals[i]) {
  309. strcat(newval, cc->vals[i]);
  310. strcat(newval, " ");
  311. }
  312. }
  313. return newval;
  314. }
  315. char *shell_esc(const char *str)
  316. {
  317. int in_quote = 0;
  318. char *cmd;
  319. unsigned char *d;
  320. const unsigned char *s;
  321. cmd = (char *)malloc(2 * strlen(str) + 1);
  322. d = (unsigned char *)cmd;
  323. s = (const unsigned char *)str;
  324. for (; *s; ++s) {
  325. if (*s == '"') {
  326. *d++ = '\\';
  327. in_quote++;
  328. }
  329. else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
  330. *d++ = '\\';
  331. }
  332. *d++ = *s;
  333. }
  334. *d = '\0';
  335. return cmd;
  336. }
  337. int external_spawn(command_t *cmd, const char *file, const char **argv)
  338. {
  339. if (!cmd->options.silent) {
  340. const char **argument = argv;
  341. printf("Executing: ");
  342. while (*argument) {
  343. printf("%s ", *argument);
  344. argument++;
  345. }
  346. puts("");
  347. }
  348. if (cmd->options.dry_run) {
  349. return 0;
  350. }
  351. #ifdef __EMX__
  352. return spawnvp(P_WAIT, file, argv);
  353. #else
  354. {
  355. pid_t pid;
  356. pid = fork();
  357. if (pid == 0) {
  358. return execvp(argv[0], (char**)argv);
  359. }
  360. else {
  361. int statuscode;
  362. waitpid(pid, &statuscode, 0);
  363. if (WIFEXITED(statuscode)) {
  364. return WEXITSTATUS(statuscode);
  365. }
  366. return 0;
  367. }
  368. }
  369. #endif
  370. }
  371. int run_command(command_t *cmd_data, count_chars *cc)
  372. {
  373. char *command;
  374. const char *spawn_args[4];
  375. count_chars tmpcc;
  376. init_count_chars(&tmpcc);
  377. if (cmd_data->program) {
  378. push_count_chars(&tmpcc, cmd_data->program);
  379. }
  380. append_count_chars(&tmpcc, cmd_data->program_opts);
  381. append_count_chars(&tmpcc, cc);
  382. command = shell_esc(flatten_count_chars(&tmpcc));
  383. spawn_args[0] = SHELL_CMD;
  384. spawn_args[1] = "-c";
  385. spawn_args[2] = command;
  386. spawn_args[3] = NULL;
  387. return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args);
  388. }
  389. /*
  390. * print configuration
  391. * shlibpath_var is used in configure.
  392. */
  393. void print_config()
  394. {
  395. #ifdef LD_RUN_PATH
  396. printf("runpath_var=%s\n", LD_RUN_PATH);
  397. #endif
  398. #ifdef LD_LIBRARY_PATH
  399. printf("shlibpath_var=%s\n", LD_LIBRARY_PATH);
  400. #endif
  401. #ifdef SHELL_CMD
  402. printf("SHELL=\"%s\"\n", SHELL_CMD);
  403. #endif
  404. }
  405. /*
  406. * Add a directory to the runtime library search path.
  407. */
  408. void add_runtimedirlib(char *arg, command_t *cmd_data)
  409. {
  410. #ifdef RPATH
  411. add_rpath(cmd_data->shared_opts.dependencies, arg);
  412. #else
  413. #endif
  414. }
  415. int parse_long_opt(char *arg, command_t *cmd_data)
  416. {
  417. char *equal_pos = strchr(arg, '=');
  418. char var[50];
  419. char value[500];
  420. if (equal_pos) {
  421. strncpy(var, arg, equal_pos - arg);
  422. var[equal_pos - arg] = 0;
  423. strcpy(value, equal_pos + 1);
  424. } else {
  425. strcpy(var, arg);
  426. }
  427. if (strcmp(var, "silent") == 0) {
  428. cmd_data->options.silent = 1;
  429. } else if (strcmp(var, "mode") == 0) {
  430. if (strcmp(value, "compile") == 0) {
  431. cmd_data->mode = mCompile;
  432. cmd_data->output = otObject;
  433. }
  434. if (strcmp(value, "link") == 0) {
  435. cmd_data->mode = mLink;
  436. cmd_data->output = otLibrary;
  437. }
  438. if (strcmp(value, "install") == 0) {
  439. cmd_data->mode = mInstall;
  440. }
  441. } else if (strcmp(var, "shared") == 0) {
  442. if (cmd_data->mode == mLink) {
  443. cmd_data->output = otDynamicLibraryOnly;
  444. }
  445. cmd_data->options.shared = 1;
  446. } else if (strcmp(var, "export-all") == 0) {
  447. cmd_data->options.export_all = 1;
  448. } else if (strcmp(var, "dry-run") == 0) {
  449. printf("Dry-run mode on!\n");
  450. cmd_data->options.dry_run = 1;
  451. } else if (strcmp(var, "version") == 0) {
  452. printf("Version " VERSION "\n");
  453. } else if (strcmp(var, "help") == 0) {
  454. printf("Sorry. No help available.\n");
  455. } else if (strcmp(var, "config") == 0) {
  456. print_config();
  457. } else if (strcmp(var, "tag") == 0) {
  458. if (strcmp(value, "CC") == 0) {
  459. /* Do nothing. */
  460. }
  461. if (strcmp(value, "CXX") == 0) {
  462. /* Do nothing. */
  463. }
  464. } else {
  465. return 0;
  466. }
  467. return 1;
  468. }
  469. /* Return 1 if we eat it. */
  470. int parse_short_opt(char *arg, command_t *cmd_data)
  471. {
  472. if (strcmp(arg, "export-dynamic") == 0) {
  473. cmd_data->options.export_dynamic = 1;
  474. return 1;
  475. }
  476. if (strcmp(arg, "module") == 0) {
  477. cmd_data->output = otModule;
  478. return 1;
  479. }
  480. if (strcmp(arg, "Zexe") == 0) {
  481. return 1;
  482. }
  483. if (strcmp(arg, "avoid-version") == 0) {
  484. return 1;
  485. }
  486. if (strcmp(arg, "prefer-pic") == 0) {
  487. cmd_data->options.pic_mode = pic_PREFER;
  488. return 1;
  489. }
  490. if (strcmp(arg, "prefer-non-pic") == 0) {
  491. cmd_data->options.pic_mode = pic_AVOID;
  492. return 1;
  493. }
  494. if (strcmp(arg, "static") == 0) {
  495. /* Don't respect it for now. */
  496. return 1;
  497. }
  498. if (cmd_data->mode == mLink) {
  499. if (strcmp(arg, "no-install") == 0) {
  500. cmd_data->options.no_install = 1;
  501. return 1;
  502. }
  503. if (arg[0] == 'L' || arg[0] == 'l') {
  504. /* Hack... */
  505. arg--;
  506. push_count_chars(cmd_data->shared_opts.dependencies, arg);
  507. return 1;
  508. } else if (arg[0] == 'R' && arg[1]) {
  509. /* -Rdir Add dir to runtime library search path. */
  510. add_runtimedirlib(&arg[1], cmd_data);
  511. return 1;
  512. }
  513. }
  514. return 0;
  515. }
  516. char *truncate_dll_name(char *path)
  517. {
  518. /* Cut DLL name down to 8 characters after removing any mod_ prefix */
  519. char *tmppath = strdup(path);
  520. char *newname = strrchr(tmppath, '/') + 1;
  521. char *ext = strrchr(tmppath, '.');
  522. int len;
  523. if (ext == NULL)
  524. return tmppath;
  525. len = ext - newname;
  526. if (strncmp(newname, "mod_", 4) == 0) {
  527. strcpy(newname, newname + 4);
  528. len -= 4;
  529. }
  530. if (len > 8) {
  531. strcpy(newname + 8, strchr(newname, '.'));
  532. }
  533. return tmppath;
  534. }
  535. long safe_strtol(const char *nptr, const char **endptr, int base)
  536. {
  537. long rv;
  538. errno = 0;
  539. rv = strtol(nptr, (char**)endptr, 10);
  540. if (errno == ERANGE) {
  541. return 0;
  542. }
  543. return rv;
  544. }
  545. /* version_info is in the form of MAJOR:MINOR:PATCH */
  546. const char *darwin_dynamic_link_function(const char *version_info)
  547. {
  548. char *newarg;
  549. long major, minor, patch;
  550. major = 0;
  551. minor = 0;
  552. patch = 0;
  553. if (version_info) {
  554. major = safe_strtol(version_info, &version_info, 10);
  555. if (version_info) {
  556. if (version_info[0] == ':') {
  557. version_info++;
  558. }
  559. minor = safe_strtol(version_info, &version_info, 10);
  560. if (version_info) {
  561. if (version_info[0] == ':') {
  562. version_info++;
  563. }
  564. patch = safe_strtol(version_info, &version_info, 10);
  565. }
  566. }
  567. }
  568. /* Avoid -dylib_compatibility_version must be greater than zero errors. */
  569. if (major == 0) {
  570. major = 1;
  571. }
  572. newarg = (char*)malloc(100);
  573. snprintf(newarg, 99,
  574. "-compatibility_version %ld -current_version %ld.%ld",
  575. major, major, minor);
  576. return newarg;
  577. }
  578. /* genlib values
  579. * 0 - static
  580. * 1 - dynamic
  581. * 2 - module
  582. */
  583. char *gen_library_name(const char *name, int genlib)
  584. {
  585. char *newarg, *newext;
  586. newarg = (char *)malloc(strlen(name) + 10);
  587. strcpy(newarg, ".libs/");
  588. if (genlib == 2 && strncmp(name, "lib", 3) == 0) {
  589. name += 3;
  590. }
  591. strcat(newarg, name);
  592. newext = strrchr(newarg, '.') + 1;
  593. switch (genlib) {
  594. case 0:
  595. strcpy(newext, STATIC_LIB_EXT);
  596. break;
  597. case 1:
  598. strcpy(newext, DYNAMIC_LIB_EXT);
  599. break;
  600. case 2:
  601. strcpy(newext, MODULE_LIB_EXT);
  602. break;
  603. }
  604. return newarg;
  605. }
  606. /* genlib values
  607. * 0 - static
  608. * 1 - dynamic
  609. * 2 - module
  610. */
  611. char *gen_install_name(const char *name, int genlib)
  612. {
  613. struct stat sb;
  614. char *newname;
  615. int rv;
  616. newname = gen_library_name(name, genlib);
  617. /* Check if it exists. If not, return NULL. */
  618. rv = stat(newname, &sb);
  619. if (rv) {
  620. return NULL;
  621. }
  622. return newname;
  623. }
  624. char *check_object_exists(command_t *cmd, const char *arg, int arglen)
  625. {
  626. char *newarg, *ext;
  627. int pass, rv;
  628. newarg = (char *)malloc(arglen + 10);
  629. memcpy(newarg, arg, arglen);
  630. newarg[arglen] = 0;
  631. ext = newarg + arglen;
  632. pass = 0;
  633. do {
  634. struct stat sb;
  635. switch (pass) {
  636. case 0:
  637. strcpy(ext, OBJECT_EXT);
  638. break;
  639. /*
  640. case 1:
  641. strcpy(ext, NO_PIC_EXT);
  642. break;
  643. */
  644. default:
  645. break;
  646. }
  647. if (!cmd->options.silent) {
  648. printf("Checking (obj): %s\n", newarg);
  649. }
  650. rv = stat(newarg, &sb);
  651. }
  652. while (rv != 0 && ++pass < 1);
  653. if (rv == 0) {
  654. if (pass == 1) {
  655. cmd->options.pic_mode = pic_AVOID;
  656. }
  657. return newarg;
  658. }
  659. return NULL;
  660. }
  661. /* libdircheck values:
  662. * 0 - no .libs suffix
  663. * 1 - .libs suffix
  664. */
  665. char *check_library_exists(command_t *cmd, const char *arg, int pathlen,
  666. int libdircheck, enum lib_type *libtype)
  667. {
  668. char *newarg, *ext;
  669. int pass, rv, newpathlen;
  670. newarg = (char *)malloc(strlen(arg) + 10);
  671. strcpy(newarg, arg);
  672. newarg[pathlen] = 0;
  673. newpathlen = pathlen;
  674. if (libdircheck) {
  675. strcat(newarg, ".libs/");
  676. newpathlen += sizeof(".libs/") - 1;
  677. }
  678. strcpy(newarg+newpathlen, arg+pathlen);
  679. ext = strrchr(newarg, '.') + 1;
  680. pass = 0;
  681. do {
  682. struct stat sb;
  683. switch (pass) {
  684. case 0:
  685. if (cmd->options.pic_mode != pic_AVOID || cmd->options.shared) {
  686. strcpy(ext, DYNAMIC_LIB_EXT);
  687. *libtype = type_DYNAMIC_LIB;
  688. break;
  689. }
  690. pass = 1;
  691. case 1:
  692. strcpy(ext, STATIC_LIB_EXT);
  693. *libtype = type_STATIC_LIB;
  694. break;
  695. case 2:
  696. strcpy(ext, MODULE_LIB_EXT);
  697. *libtype = type_MODULE_LIB;
  698. break;
  699. case 3:
  700. strcpy(ext, OBJECT_EXT);
  701. *libtype = type_OBJECT;
  702. break;
  703. default:
  704. *libtype = type_UNKNOWN;
  705. break;
  706. }
  707. if (!cmd->options.silent) {
  708. printf("Checking (lib): %s\n", newarg);
  709. }
  710. rv = stat(newarg, &sb);
  711. }
  712. while (rv != 0 && ++pass < 4);
  713. if (rv == 0) {
  714. return newarg;
  715. }
  716. return NULL;
  717. }
  718. char * load_install_path(const char *arg)
  719. {
  720. FILE *f;
  721. char *path;
  722. path = malloc(PATH_MAX);
  723. f = fopen(arg,"r");
  724. if (f == NULL) {
  725. return NULL;
  726. }
  727. fgets(path, PATH_MAX, f);
  728. fclose(f);
  729. if (path[strlen(path)-1] == '\n') {
  730. path[strlen(path)-1] = '\0';
  731. }
  732. /* Check that we have an absolute path.
  733. * Otherwise the file could be a GNU libtool file.
  734. */
  735. if (path[0] != '/') {
  736. return NULL;
  737. }
  738. return path;
  739. }
  740. char * load_noinstall_path(const char *arg, int pathlen)
  741. {
  742. char *newarg, *expanded_path;
  743. int newpathlen;
  744. newarg = (char *)malloc(strlen(arg) + 10);
  745. strcpy(newarg, arg);
  746. newarg[pathlen] = 0;
  747. newpathlen = pathlen;
  748. strcat(newarg, ".libs");
  749. newpathlen += sizeof(".libs") - 1;
  750. newarg[newpathlen] = 0;
  751. #ifdef HAS_REALPATH
  752. expanded_path = malloc(PATH_MAX);
  753. expanded_path = realpath(newarg, expanded_path);
  754. /* Uh, oh. There was an error. Fall back on our first guess. */
  755. if (!expanded_path) {
  756. expanded_path = newarg;
  757. }
  758. #else
  759. /* We might get ../ or something goofy. Oh, well. */
  760. expanded_path = newarg;
  761. #endif
  762. return expanded_path;
  763. }
  764. /* Read the final install location and add it to runtime library search path. */
  765. #ifdef RPATH
  766. void add_rpath(count_chars *cc, const char *path)
  767. {
  768. int size = 0;
  769. char *tmp;
  770. #ifdef LINKER_FLAG_PREFIX
  771. size = strlen(LINKER_FLAG_PREFIX);
  772. #endif
  773. size = size + strlen(path) + strlen(RPATH) + 2;
  774. tmp = malloc(size);
  775. if (tmp == NULL) {
  776. return;
  777. }
  778. #ifdef LINKER_FLAG_PREFIX
  779. strcpy(tmp, LINKER_FLAG_PREFIX);
  780. strcat(tmp, RPATH);
  781. #else
  782. strcpy(tmp, RPATH);
  783. #endif
  784. #ifndef LINKER_FLAG_NO_EQUALS
  785. strcat(tmp, "=");
  786. #endif
  787. strcat(tmp, path);
  788. push_count_chars(cc, tmp);
  789. }
  790. void add_rpath_file(count_chars *cc, const char *arg)
  791. {
  792. const char *path;
  793. path = load_install_path(arg);
  794. if (path) {
  795. add_rpath(cc, path);
  796. }
  797. }
  798. void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen)
  799. {
  800. const char *path;
  801. path = load_noinstall_path(arg, pathlen);
  802. if (path) {
  803. add_rpath(cc, path);
  804. }
  805. }
  806. #endif
  807. #ifdef DYNAMIC_LINK_NO_INSTALL
  808. void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen,
  809. int extlen)
  810. {
  811. const char *install_path, *current_path, *name;
  812. char *exp_argument;
  813. int i_p_len, c_p_len, name_len, dyext_len, cur_len;
  814. install_path = load_install_path(arg);
  815. current_path = load_noinstall_path(arg, pathlen);
  816. if (!install_path || !current_path) {
  817. return;
  818. }
  819. push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
  820. i_p_len = strlen(install_path);
  821. c_p_len = strlen(current_path);
  822. name = arg+pathlen;
  823. name_len = extlen-pathlen;
  824. dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
  825. /* No, we need to replace the extension. */
  826. exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) +
  827. (dyext_len*2) + 2);
  828. cur_len = 0;
  829. strcpy(exp_argument, install_path);
  830. cur_len += i_p_len;
  831. exp_argument[cur_len++] = '/';
  832. strncpy(exp_argument+cur_len, name, extlen-pathlen);
  833. cur_len += name_len;
  834. strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
  835. cur_len += dyext_len;
  836. exp_argument[cur_len++] = ':';
  837. strcpy(exp_argument+cur_len, current_path);
  838. cur_len += c_p_len;
  839. exp_argument[cur_len++] = '/';
  840. strncpy(exp_argument+cur_len, name, extlen-pathlen);
  841. cur_len += name_len;
  842. strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
  843. cur_len += dyext_len;
  844. push_count_chars(cc, exp_argument);
  845. }
  846. #endif
  847. /* use -L -llibname to allow to use installed libraries */
  848. void add_minus_l(count_chars *cc, const char *arg)
  849. {
  850. char *newarg;
  851. char *name = strrchr(arg, '/');
  852. char *file = strrchr(arg, '.');
  853. char *lib = strstr(name, "lib");
  854. if (name !=NULL && file != NULL && lib == name+1) {
  855. *name = '\0';
  856. *file = '\0';
  857. file = name;
  858. file = file+4;
  859. push_count_chars(cc, "-L");
  860. push_count_chars(cc, arg);
  861. /* we need one argument like -lapr-1 */
  862. newarg = malloc(strlen(file) + 3);
  863. strcpy(newarg, "-l");
  864. strcat(newarg, file);
  865. push_count_chars(cc, newarg);
  866. } else {
  867. push_count_chars(cc, arg);
  868. }
  869. }
  870. void add_linker_flag_prefix(count_chars *cc, const char *arg)
  871. {
  872. #ifndef LINKER_FLAG_PREFIX
  873. push_count_chars(cc, arg);
  874. #else
  875. char *newarg;
  876. newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
  877. strcpy(newarg, LINKER_FLAG_PREFIX);
  878. strcat(newarg, arg);
  879. push_count_chars(cc, newarg);
  880. #endif
  881. }
  882. int parse_input_file_name(char *arg, command_t *cmd_data)
  883. {
  884. char *ext = strrchr(arg, '.');
  885. char *name = strrchr(arg, '/');
  886. int pathlen;
  887. enum lib_type libtype;
  888. char *newarg;
  889. if (!ext) {
  890. return 0;
  891. }
  892. ext++;
  893. if (name == NULL) {
  894. name = strrchr(arg, '\\');
  895. if (name == NULL) {
  896. name = arg;
  897. } else {
  898. name++;
  899. }
  900. } else {
  901. name++;
  902. }
  903. pathlen = name - arg;
  904. if (strcmp(ext, "lo") == 0) {
  905. newarg = check_object_exists(cmd_data, arg, ext - arg);
  906. if (!newarg) {
  907. printf("Can not find suitable object file for %s\n", arg);
  908. exit(1);
  909. }
  910. if (cmd_data->mode != mLink) {
  911. push_count_chars(cmd_data->arglist, newarg);
  912. }
  913. else {
  914. push_count_chars(cmd_data->obj_files, newarg);
  915. }
  916. return 1;
  917. }
  918. if (strcmp(ext, "la") == 0) {
  919. switch (cmd_data->mode) {
  920. case mLink:
  921. /* Try the .libs dir first! */
  922. newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype);
  923. if (!newarg) {
  924. /* Try the normal dir next. */
  925. newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype);
  926. if (!newarg) {
  927. printf("Can not find suitable library for %s\n", arg);
  928. exit(1);
  929. }
  930. }
  931. /* It is not ok to just add the file: a library may added with:
  932. 1 - -L path library_name. (For *.so in Linux).
  933. 2 - library_name.
  934. */
  935. #ifdef ADD_MINUS_L
  936. if (libtype == type_DYNAMIC_LIB) {
  937. add_minus_l(cmd_data->shared_opts.dependencies, newarg);
  938. } else {
  939. push_count_chars(cmd_data->shared_opts.dependencies, newarg);
  940. }
  941. #else
  942. push_count_chars(cmd_data->shared_opts.dependencies, newarg);
  943. #endif
  944. if (libtype == type_DYNAMIC_LIB) {
  945. if (cmd_data->options.no_install) {
  946. #ifdef RPATH
  947. add_rpath_noinstall(cmd_data->shared_opts.dependencies,
  948. arg, pathlen);
  949. #endif
  950. #ifdef DYNAMIC_LINK_NO_INSTALL
  951. /*
  952. * This doesn't work as Darwin's linker has no way to
  953. * override at link-time the search paths for a
  954. * non-installed library.
  955. */
  956. /*
  957. add_dylink_noinstall(cmd_data->shared_opts.dependencies,
  958. arg, pathlen, ext - arg);
  959. */
  960. #endif
  961. }
  962. else {
  963. #ifdef RPATH
  964. add_rpath_file(cmd_data->shared_opts.dependencies, arg);
  965. #endif
  966. }
  967. }
  968. break;
  969. case mInstall:
  970. /* If we've already recorded a library to install, we're most
  971. * likely getting the .la file that we want to install as.
  972. * The problem is that we need to add it as the directory,
  973. * not the .la file itself. Otherwise, we'll do odd things.
  974. */
  975. if (cmd_data->output == otLibrary) {
  976. arg[pathlen] = '\0';
  977. push_count_chars(cmd_data->arglist, arg);
  978. }
  979. else {
  980. cmd_data->output = otLibrary;
  981. cmd_data->output_name = arg;
  982. cmd_data->static_name.install = gen_install_name(arg, 0);
  983. cmd_data->shared_name.install = gen_install_name(arg, 1);
  984. cmd_data->module_name.install = gen_install_name(arg, 2);
  985. }
  986. break;
  987. default:
  988. break;
  989. }
  990. return 1;
  991. }
  992. if (strcmp(ext, "c") == 0) {
  993. /* If we don't already have an idea what our output name will be. */
  994. if (cmd_data->basename == NULL) {
  995. cmd_data->basename = (char *)malloc(strlen(arg) + 4);
  996. strcpy(cmd_data->basename, arg);
  997. strcpy(strrchr(cmd_data->basename, '.') + 1, "lo");
  998. cmd_data->fake_output_name = strrchr(cmd_data->basename, '/');
  999. if (cmd_data->fake_output_name) {
  1000. cmd_data->fake_output_name++;
  1001. }
  1002. else {
  1003. cmd_data->fake_output_name = cmd_data->basename;
  1004. }
  1005. }
  1006. }
  1007. return 0;
  1008. }
  1009. int parse_output_file_name(char *arg, command_t *cmd_data)
  1010. {
  1011. char *name = strrchr(arg, '/');
  1012. char *ext = strrchr(arg, '.');
  1013. char *newarg = NULL;
  1014. int pathlen;
  1015. cmd_data->fake_output_name = arg;
  1016. if (name) {
  1017. name++;
  1018. }
  1019. else {
  1020. name = strrchr(arg, '\\');
  1021. if (name == NULL) {
  1022. name = arg;
  1023. }
  1024. else {
  1025. name++;
  1026. }
  1027. }
  1028. if (!ext) {
  1029. cmd_data->basename = arg;
  1030. cmd_data->output = otProgram;
  1031. #if defined(_OSD_POSIX)
  1032. cmd_data->options.pic_mode = pic_AVOID;
  1033. #endif
  1034. newarg = (char *)malloc(strlen(arg) + 5);
  1035. strcpy(newarg, arg);
  1036. #ifdef EXE_EXT
  1037. strcat(newarg, EXE_EXT);
  1038. #endif
  1039. cmd_data->output_name = newarg;
  1040. return 1;
  1041. }
  1042. ext++;
  1043. pathlen = name - arg;
  1044. if (strcmp(ext, "la") == 0) {
  1045. assert(cmd_data->mode == mLink);
  1046. cmd_data->basename = arg;
  1047. cmd_data->static_name.normal = gen_library_name(arg, 0);
  1048. cmd_data->shared_name.normal = gen_library_name(arg, 1);
  1049. cmd_data->module_name.normal = gen_library_name(arg, 2);
  1050. cmd_data->static_name.install = gen_install_name(arg, 0);
  1051. cmd_data->shared_name.install = gen_install_name(arg, 1);
  1052. cmd_data->module_name.install = gen_install_name(arg, 2);
  1053. #ifdef TRUNCATE_DLL_NAME
  1054. if (shared) {
  1055. arg = truncate_dll_name(arg);
  1056. }
  1057. #endif
  1058. cmd_data->output_name = arg;
  1059. return 1;
  1060. }
  1061. if (strcmp(ext, "lo") == 0) {
  1062. cmd_data->basename = arg;
  1063. cmd_data->output = otObject;
  1064. newarg = (char *)malloc(strlen(arg) + 2);
  1065. strcpy(newarg, arg);
  1066. ext = strrchr(newarg, '.') + 1;
  1067. strcpy(ext, OBJECT_EXT);
  1068. cmd_data->output_name = newarg;
  1069. return 1;
  1070. }
  1071. return 0;
  1072. }
  1073. /* returns just a file's name without path or extension */
  1074. char *nameof(char *fullpath)
  1075. {
  1076. char buffer[1024];
  1077. char *ext;
  1078. char *name = strrchr(fullpath, '/');
  1079. if (name == NULL) {
  1080. name = strrchr(fullpath, '\\');
  1081. }
  1082. if (name == NULL) {
  1083. name = fullpath;
  1084. } else {
  1085. name++;
  1086. }
  1087. strcpy(buffer, name);
  1088. ext = strrchr(buffer, '.');
  1089. if (ext) {
  1090. *ext = 0;
  1091. return strdup(buffer);
  1092. }
  1093. return name;
  1094. }
  1095. void parse_args(int argc, char *argv[], command_t *cmd_data)
  1096. {
  1097. int a;
  1098. char *arg;
  1099. int argused;
  1100. for (a = 1; a < argc; a++) {
  1101. arg = argv[a];
  1102. argused = 1;
  1103. if (arg[0] == '-') {
  1104. if (arg[1] == '-') {
  1105. argused = parse_long_opt(arg + 2, cmd_data);
  1106. }
  1107. else {
  1108. argused = parse_short_opt(arg + 1, cmd_data);
  1109. }
  1110. /* We haven't done anything with it yet, try some of the
  1111. * more complicated short opts... */
  1112. if (argused == 0 && a + 1 < argc) {
  1113. if (arg[1] == 'o' && !arg[2]) {
  1114. arg = argv[++a];
  1115. argused = parse_output_file_name(arg, cmd_data);
  1116. } else if (strcmp(arg+1, "MT") == 0) {
  1117. if (!cmd_data->options.silent) {
  1118. printf("Adding: %s", arg);
  1119. }
  1120. push_count_chars(cmd_data->arglist, arg);
  1121. arg = argv[++a];
  1122. if (!cmd_data->options.silent) {
  1123. printf(" %s\n", arg);
  1124. }
  1125. push_count_chars(cmd_data->arglist, arg);
  1126. argused = 1;
  1127. } else if (strcmp(arg+1, "rpath") == 0) {
  1128. /* Aha, we should try to link both! */
  1129. cmd_data->install_path = argv[++a];
  1130. argused = 1;
  1131. } else if (strcmp(arg+1, "version-info") == 0) {
  1132. /* Store for later deciphering */
  1133. cmd_data->version_info = argv[++a];
  1134. argused = 1;
  1135. } else if (strcmp(arg+1, "export-symbols-regex") == 0) {
  1136. /* Skip the argument. */
  1137. ++a;
  1138. argused = 1;
  1139. } else if (arg[1] == 'R' && !arg[2]) {
  1140. /* -R dir Add dir to runtime library search path. */
  1141. add_runtimedirlib(argv[++a], cmd_data);
  1142. argused = 1;
  1143. }
  1144. }
  1145. } else {
  1146. argused = parse_input_file_name(arg, cmd_data);
  1147. }
  1148. if (!argused) {
  1149. if (!cmd_data->options.silent) {
  1150. printf("Adding: %s\n", arg);
  1151. }
  1152. push_count_chars(cmd_data->arglist, arg);
  1153. }
  1154. }
  1155. }
  1156. int explode_static_lib(const char *lib, command_t *cmd_data)
  1157. {
  1158. char tmpdir[1024];
  1159. char savewd[1024];
  1160. char cmd[1024];
  1161. const char *name;
  1162. DIR *dir;
  1163. struct dirent *entry;
  1164. /* Bah! */
  1165. if (cmd_data->options.dry_run) {
  1166. return 0;
  1167. }
  1168. strcpy(tmpdir, lib);
  1169. strcat(tmpdir, ".exploded");
  1170. mkdir(tmpdir, 0);
  1171. push_count_chars(cmd_data->tmp_dirs, strdup(tmpdir));
  1172. getcwd(savewd, sizeof(savewd));
  1173. if (chdir(tmpdir) != 0)
  1174. return 1;
  1175. strcpy(cmd, LIBRARIAN " x ");
  1176. name = strrchr(lib, '/');
  1177. if (name) {
  1178. name++;
  1179. } else {
  1180. name = lib;
  1181. }
  1182. strcat(cmd, "../");
  1183. strcat(cmd, name);
  1184. system(cmd);
  1185. chdir(savewd);
  1186. dir = opendir(tmpdir);
  1187. while ((entry = readdir(dir)) != NULL) {
  1188. if (entry->d_name[0] != '.') {
  1189. strcpy(cmd, tmpdir);
  1190. strcat(cmd, "/");
  1191. strcat(cmd, entry->d_name);
  1192. push_count_chars(cmd_data->arglist, strdup(cmd));
  1193. }
  1194. }
  1195. closedir(dir);
  1196. return 0;
  1197. }
  1198. #ifdef GEN_EXPORTS
  1199. void generate_def_file(command_t *cmd_data)
  1200. {
  1201. char def_file[1024];
  1202. char implib_file[1024];
  1203. char *ext;
  1204. FILE *hDef;
  1205. char *export_args[1024];
  1206. int num_export_args = 0;
  1207. char *cmd;
  1208. int cmd_size = 0;
  1209. int a;
  1210. if (cmd_data->output_name) {
  1211. strcpy(def_file, cmd_data->output_name);
  1212. strcat(def_file, ".def");
  1213. hDef = fopen(def_file, "w");
  1214. if (hDef != NULL) {
  1215. fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
  1216. fprintf(hDef, "DATA NONSHARED\n");
  1217. fprintf(hDef, "EXPORTS\n");
  1218. fclose(hDef);
  1219. for (a = 0; a < cmd_data->num_obj_files; a++) {
  1220. cmd_size += strlen(cmd_data->obj_files[a]) + 1;
  1221. }
  1222. cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
  1223. cmd = (char *)malloc(cmd_size);
  1224. strcpy(cmd, GEN_EXPORTS);
  1225. for (a=0; a < cmd_data->num_obj_files; a++) {
  1226. strcat(cmd, " ");
  1227. strcat(cmd, cmd_data->obj_files[a] );
  1228. }
  1229. strcat(cmd, ">>");
  1230. strcat(cmd, def_file);
  1231. puts(cmd);
  1232. export_args[num_export_args++] = SHELL_CMD;
  1233. export_args[num_export_args++] = "-c";
  1234. export_args[num_export_args++] = cmd;
  1235. export_args[num_export_args++] = NULL;
  1236. external_spawn(cmd_data, export_args[0], (const char**)export_args);
  1237. cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
  1238. /* Now make an import library for the dll */
  1239. num_export_args = 0;
  1240. export_args[num_export_args++] = DEF2IMPLIB_CMD;
  1241. export_args[num_export_args++] = "-o";
  1242. strcpy(implib_file, ".libs/");
  1243. strcat(implib_file, cmd_data->basename);
  1244. ext = strrchr(implib_file, '.');
  1245. if (ext)
  1246. *ext = 0;
  1247. strcat(implib_file, ".");
  1248. strcat(implib_file, STATIC_LIB_EXT);
  1249. export_args[num_export_args++] = implib_file;
  1250. export_args[num_export_args++] = def_file;
  1251. export_args[num_export_args++] = NULL;
  1252. external_spawn(cmd_data, export_args[0], (const char**)export_args);
  1253. }
  1254. }
  1255. }
  1256. #endif
  1257. const char* expand_path(const char *relpath)
  1258. {
  1259. char foo[PATH_MAX], *newpath;
  1260. getcwd(foo, PATH_MAX-1);
  1261. newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2);
  1262. strcat(newpath, foo);
  1263. strcat(newpath, "/");
  1264. strcat(newpath, relpath);
  1265. return newpath;
  1266. }
  1267. void link_fixup(command_t *c)
  1268. {
  1269. /* If we were passed an -rpath directive, we need to build
  1270. * shared objects too. Otherwise, we should only create static
  1271. * libraries.
  1272. */
  1273. if (!c->install_path && (c->output == otDynamicLibraryOnly ||
  1274. c->output == otModule || c->output == otLibrary)) {
  1275. c->output = otStaticLibraryOnly;
  1276. }
  1277. if (c->output == otDynamicLibraryOnly ||
  1278. c->output == otModule ||
  1279. c->output == otLibrary) {
  1280. push_count_chars(c->shared_opts.normal, "-o");
  1281. if (c->output == otModule) {
  1282. push_count_chars(c->shared_opts.normal, c->module_name.normal);
  1283. }
  1284. else {
  1285. char *tmp;
  1286. push_count_chars(c->shared_opts.normal, c->shared_name.normal);
  1287. #ifdef DYNAMIC_INSTALL_NAME
  1288. push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME);
  1289. tmp = (char*)malloc(PATH_MAX);
  1290. strcat(tmp, c->install_path);
  1291. strcat(tmp, strrchr(c->shared_name.normal, '/'));
  1292. push_count_chars(c->shared_opts.normal, tmp);
  1293. #endif
  1294. }
  1295. append_count_chars(c->shared_opts.normal, c->obj_files);
  1296. append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies);
  1297. if (c->options.export_all) {
  1298. #ifdef GEN_EXPORTS
  1299. generate_def_file(c);
  1300. #endif
  1301. }
  1302. }
  1303. if (c->output == otLibrary || c->output == otStaticLibraryOnly) {
  1304. push_count_chars(c->static_opts.normal, "-o");
  1305. push_count_chars(c->static_opts.normal, c->output_name);
  1306. }
  1307. if (c->output == otProgram) {
  1308. if (c->output_name) {
  1309. push_count_chars(c->arglist, "-o");
  1310. push_count_chars(c->arglist, c->output_name);
  1311. append_count_chars(c->arglist, c->obj_files);
  1312. append_count_chars(c->arglist, c->shared_opts.dependencies);
  1313. #ifdef DYNAMIC_LINK_OPTS
  1314. if (c->options.pic_mode != pic_AVOID) {
  1315. push_count_chars(c->arglist, DYNAMIC_LINK_OPTS);
  1316. }
  1317. #endif
  1318. }
  1319. }
  1320. }
  1321. void post_parse_fixup(command_t *cmd_data)
  1322. {
  1323. switch (cmd_data->mode)
  1324. {
  1325. case mCompile:
  1326. #ifdef PIC_FLAG
  1327. if (cmd_data->options.pic_mode != pic_AVOID) {
  1328. push_count_chars(cmd_data->arglist, PIC_FLAG);
  1329. }
  1330. #endif
  1331. if (cmd_data->output_name) {
  1332. push_count_chars(cmd_data->arglist, "-o");
  1333. push_count_chars(cmd_data->arglist, cmd_data->output_name);
  1334. }
  1335. break;
  1336. case mLink:
  1337. link_fixup(cmd_data);
  1338. break;
  1339. case mInstall:
  1340. if (cmd_data->output == otLibrary) {
  1341. link_fixup(cmd_data);
  1342. }
  1343. default:
  1344. break;
  1345. }
  1346. #if USE_OMF
  1347. if (cmd_data->output == otObject ||
  1348. cmd_data->output == otProgram ||
  1349. cmd_data->output == otLibrary ||
  1350. cmd_data->output == otDynamicLibraryOnly) {
  1351. push_count_chars(cmd_data->arglist, "-Zomf");
  1352. }
  1353. #endif
  1354. if (cmd_data->options.shared &&
  1355. (cmd_data->output == otObject ||
  1356. cmd_data->output == otLibrary ||
  1357. cmd_data->output == otDynamicLibraryOnly)) {
  1358. #ifdef SHARE_SW
  1359. push_count_chars(cmd_data->arglist, SHARE_SW);
  1360. #endif
  1361. }
  1362. }
  1363. int run_mode(command_t *cmd_data)
  1364. {
  1365. int rv;
  1366. count_chars *cctemp;
  1367. cctemp = (count_chars*)malloc(sizeof(count_chars));
  1368. init_count_chars(cctemp);
  1369. switch (cmd_data->mode)
  1370. {
  1371. case mCompile:
  1372. rv = run_command(cmd_data, cmd_data->arglist);
  1373. if (rv) {
  1374. return rv;
  1375. }
  1376. break;
  1377. case mInstall:
  1378. /* Well, we'll assume it's a file going to a directory... */
  1379. /* For brain-dead install-sh based scripts, we have to repeat
  1380. * the command N-times. install-sh should die.
  1381. */
  1382. if (!cmd_data->output_name) {
  1383. rv = run_command(cmd_data, cmd_data->arglist);
  1384. if (rv) {
  1385. return rv;
  1386. }
  1387. }
  1388. if (cmd_data->output_name) {
  1389. append_count_chars(cctemp, cmd_data->arglist);
  1390. insert_count_chars(cctemp,
  1391. cmd_data->output_name,
  1392. cctemp->num - 1);
  1393. rv = run_command(cmd_data, cctemp);
  1394. if (rv) {
  1395. return rv;
  1396. }
  1397. clear_count_chars(cctemp);
  1398. }
  1399. if (cmd_data->static_name.install) {
  1400. append_count_chars(cctemp, cmd_data->arglist);
  1401. insert_count_chars(cctemp,
  1402. cmd_data->static_name.install,
  1403. cctemp->num - 1);
  1404. rv = run_command(cmd_data, cctemp);
  1405. if (rv) {
  1406. return rv;
  1407. }
  1408. clear_count_chars(cctemp);
  1409. }
  1410. if (cmd_data->shared_name.install) {
  1411. append_count_chars(cctemp, cmd_data->arglist);
  1412. insert_count_chars(cctemp,
  1413. cmd_data->shared_name.install,
  1414. cctemp->num - 1);
  1415. rv = run_command(cmd_data, cctemp);
  1416. if (rv) {
  1417. return rv;
  1418. }
  1419. clear_count_chars(cctemp);
  1420. }
  1421. if (cmd_data->module_name.install) {
  1422. append_count_chars(cctemp, cmd_data->arglist);
  1423. insert_count_chars(cctemp,
  1424. cmd_data->module_name.install,
  1425. cctemp->num - 1);
  1426. rv = run_command(cmd_data, cctemp);
  1427. if (rv) {
  1428. return rv;
  1429. }
  1430. clear_count_chars(cctemp);
  1431. }
  1432. break;
  1433. case mLink:
  1434. if (!cmd_data->options.dry_run) {
  1435. /* Check first to see if the dir already exists! */
  1436. mode_t old_umask;
  1437. old_umask = umask(0);
  1438. umask(old_umask);
  1439. mkdir(".libs", ~old_umask);
  1440. }
  1441. if (cmd_data->output == otStaticLibraryOnly ||
  1442. cmd_data->output == otLibrary) {
  1443. #ifdef RANLIB
  1444. const char *lib_args[3];
  1445. #endif
  1446. /* Removes compiler! */
  1447. cmd_data->program = LIBRARIAN;
  1448. push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS);
  1449. push_count_chars(cmd_data->program_opts,
  1450. cmd_data->static_name.normal);
  1451. rv = run_command(cmd_data, cmd_data->obj_files);
  1452. if (rv) {
  1453. return rv;
  1454. }
  1455. #ifdef RANLIB
  1456. lib_args[0] = RANLIB;
  1457. lib_args[1] = cmd_data->static_name.normal;
  1458. lib_args[2] = NULL;
  1459. external_spawn(cmd_data, RANLIB, lib_args);
  1460. #endif
  1461. }
  1462. if (cmd_data->output == otDynamicLibraryOnly ||
  1463. cmd_data->output == otModule ||
  1464. cmd_data->output == otLibrary) {
  1465. cmd_data->program = NULL;
  1466. clear_count_chars(cmd_data->program_opts);
  1467. append_count_chars(cmd_data->program_opts, cmd_data->arglist);
  1468. if (cmd_data->output != otModule) {
  1469. #ifdef SHARED_OPTS
  1470. push_count_chars(cmd_data->program_opts, SHARED_OPTS);
  1471. #endif
  1472. #ifdef dynamic_link_version_func
  1473. push_count_chars(cmd_data->program_opts,
  1474. dynamic_link_version_func(cmd_data->version_info));
  1475. #endif
  1476. }
  1477. if (cmd_data->output == otModule) {
  1478. #ifdef MODULE_OPTS
  1479. push_count_chars(cmd_data->program_opts, MODULE_OPTS);
  1480. #endif
  1481. }
  1482. #ifdef DYNAMIC_LINK_OPTS
  1483. if (cmd_data->options.pic_mode != pic_AVOID) {
  1484. push_count_chars(cmd_data->program_opts,
  1485. DYNAMIC_LINK_OPTS);
  1486. }
  1487. #endif
  1488. rv = run_command(cmd_data, cmd_data->shared_opts.normal);
  1489. if (rv) {
  1490. return rv;
  1491. }
  1492. }
  1493. if (cmd_data->output == otProgram) {
  1494. rv = run_command(cmd_data, cmd_data->arglist);
  1495. if (rv) {
  1496. return rv;
  1497. }
  1498. }
  1499. break;
  1500. default:
  1501. break;
  1502. }
  1503. return 0;
  1504. }
  1505. void cleanup_tmp_dir(const char *dirname)
  1506. {
  1507. DIR *dir;
  1508. struct dirent *entry;
  1509. char fullname[1024];
  1510. dir = opendir(dirname);
  1511. if (dir == NULL)
  1512. return;
  1513. while ((entry = readdir(dir)) != NULL) {
  1514. if (entry->d_name[0] != '.') {
  1515. strcpy(fullname, dirname);
  1516. strcat(fullname, "/");
  1517. strcat(fullname, entry->d_name);
  1518. remove(fullname);
  1519. }
  1520. }
  1521. rmdir(dirname);
  1522. }
  1523. void cleanup_tmp_dirs(command_t *cmd_data)
  1524. {
  1525. int d;
  1526. for (d = 0; d < cmd_data->tmp_dirs->num; d++) {
  1527. cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]);
  1528. }
  1529. }
  1530. int ensure_fake_uptodate(command_t *cmd_data)
  1531. {
  1532. /* FIXME: could do the stat/touch here, but nah... */
  1533. const char *touch_args[3];
  1534. if (cmd_data->mode == mInstall) {
  1535. return 0;
  1536. }
  1537. touch_args[0] = "touch";
  1538. touch_args[1] = cmd_data->fake_output_name;
  1539. touch_args[2] = NULL;
  1540. return external_spawn(cmd_data, "touch", touch_args);
  1541. }
  1542. /* Store the install path in the *.la file */
  1543. int add_for_runtime(command_t *cmd_data)
  1544. {
  1545. if (cmd_data->mode == mInstall) {
  1546. return 0;
  1547. }
  1548. if (cmd_data->output == otDynamicLibraryOnly ||
  1549. cmd_data->output == otLibrary) {
  1550. FILE *f=fopen(cmd_data->fake_output_name,"w");
  1551. if (f == NULL) {
  1552. return -1;
  1553. }
  1554. fprintf(f,"%s\n", cmd_data->install_path);
  1555. fclose(f);
  1556. return(0);
  1557. } else {
  1558. return(ensure_fake_uptodate(cmd_data));
  1559. }
  1560. }
  1561. int main(int argc, char *argv[])
  1562. {
  1563. int rc;
  1564. command_t cmd_data;
  1565. memset(&cmd_data, 0, sizeof(cmd_data));
  1566. cmd_data.options.pic_mode = pic_UNKNOWN;
  1567. cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars));
  1568. init_count_chars(cmd_data.program_opts);
  1569. cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars));
  1570. init_count_chars(cmd_data.arglist);
  1571. cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars));
  1572. init_count_chars(cmd_data.tmp_dirs);
  1573. cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars));
  1574. init_count_chars(cmd_data.obj_files);
  1575. cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars));
  1576. init_count_chars(cmd_data.dep_rpaths);
  1577. cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars));
  1578. init_count_chars(cmd_data.rpaths);
  1579. cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars));
  1580. init_count_chars(cmd_data.static_opts.normal);
  1581. cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars));
  1582. init_count_chars(cmd_data.shared_opts.normal);
  1583. cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars));
  1584. init_count_chars(cmd_data.shared_opts.dependencies);
  1585. cmd_data.mode = mUnknown;
  1586. cmd_data.output = otGeneral;
  1587. parse_args(argc, argv, &cmd_data);
  1588. post_parse_fixup(&cmd_data);
  1589. if (cmd_data.mode == mUnknown) {
  1590. exit(0);
  1591. }
  1592. rc = run_mode(&cmd_data);
  1593. if (!rc) {
  1594. add_for_runtime(&cmd_data);
  1595. }
  1596. cleanup_tmp_dirs(&cmd_data);
  1597. return rc;
  1598. }