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 17#include <stdio.h> 18#include <string.h> 19#include <stdlib.h> 20#include <sys/stat.h> 21#include <sys/types.h> 22#if !defined(__MINGW32__) 23#include <sys/wait.h> 24#endif 25#include <unistd.h> 26#include <dirent.h> 27#include <errno.h> 28#include <assert.h> 29 30#ifdef __EMX__ 31# define SHELL_CMD "sh" 32# define GEN_EXPORTS "emxexp" 33# define DEF2IMPLIB_CMD "emximp" 34# define SHARE_SW "-Zdll -Zmtd" 35# define USE_OMF 1 36# define TRUNCATE_DLL_NAME 37# define DYNAMIC_LIB_EXT "dll" 38# define EXE_EXT ".exe" 39 40# if USE_OMF 41 /* OMF is the native format under OS/2 */ 42# define STATIC_LIB_EXT "lib" 43# define OBJECT_EXT "obj" 44# define LIBRARIAN "emxomfar" 45# define LIBRARIAN_OPTS "cr" 46# else 47 /* but the alternative, a.out, can fork() which is sometimes necessary */ 48# define STATIC_LIB_EXT "a" 49# define OBJECT_EXT "o" 50# define LIBRARIAN "ar" 51# define LIBRARIAN_OPTS "cr" 52# endif 53#endif 54 55#if defined(__APPLE__) 56# define SHELL_CMD "/bin/sh" 57# define DYNAMIC_LIB_EXT "dylib" 58# define MODULE_LIB_EXT "bundle" 59# define STATIC_LIB_EXT "a" 60# define OBJECT_EXT "o" 61# define LIBRARIAN "ar" 62# define LIBRARIAN_OPTS "cr" 63/* man libtool(1) documents ranlib option of -c. */ 64# define RANLIB "ranlib" 65# define PIC_FLAG "-fPIC -fno-common" 66# define SHARED_OPTS "-dynamiclib" 67# define MODULE_OPTS "-bundle -dynamic" 68# define DYNAMIC_LINK_OPTS "-flat_namespace" 69# define DYNAMIC_LINK_UNDEFINED "-undefined suppress" 70# define dynamic_link_version_func darwin_dynamic_link_function 71# define DYNAMIC_INSTALL_NAME "-install_name" 72# define DYNAMIC_LINK_NO_INSTALL "-dylib_file" 73# define HAS_REALPATH 74/*-install_name /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */ 75# define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH" 76#endif 77 78#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) 79# define SHELL_CMD "/bin/sh" 80# define DYNAMIC_LIB_EXT "so" 81# define MODULE_LIB_EXT "so" 82# define STATIC_LIB_EXT "a" 83# define OBJECT_EXT "o" 84# define LIBRARIAN "ar" 85# define LIBRARIAN_OPTS "cr" 86# define RANLIB "ranlib" 87# define PIC_FLAG "-fPIC" 88# define RPATH "-rpath" 89# define SHARED_OPTS "-shared" 90# define MODULE_OPTS "-shared" 91# define DYNAMIC_LINK_OPTS "-export-dynamic" 92# define LINKER_FLAG_PREFIX "-Wl," 93# define ADD_MINUS_L 94# define LD_RUN_PATH "LD_RUN_PATH" 95# define LD_LIBRARY_PATH "LD_LIBRARY_PATH" 96#endif 97 98#if defined(sun) 99# define SHELL_CMD "/bin/sh" 100# define DYNAMIC_LIB_EXT "so" 101# define MODULE_LIB_EXT "so" 102# define STATIC_LIB_EXT "a" 103# define OBJECT_EXT "o" 104# define LIBRARIAN "ar" 105# define LIBRARIAN_OPTS "cr" 106# define RANLIB "ranlib" 107# define PIC_FLAG "-KPIC" 108# define RPATH "-R" 109# define SHARED_OPTS "-G" 110# define MODULE_OPTS "-G" 111# define DYNAMIC_LINK_OPTS "" 112# define LINKER_FLAG_NO_EQUALS 113# define ADD_MINUS_L 114# define HAS_REALPATH 115# define LD_RUN_PATH "LD_RUN_PATH" 116# define LD_LIBRARY_PATH "LD_LIBRARY_PATH" 117#endif 118 119#if defined(_OSD_POSIX) 120# define SHELL_CMD "/usr/bin/sh" 121# define DYNAMIC_LIB_EXT "so" 122# define MODULE_LIB_EXT "so" 123# define STATIC_LIB_EXT "a" 124# define OBJECT_EXT "o" 125# define LIBRARIAN "ar" 126# define LIBRARIAN_OPTS "cr" 127# define SHARED_OPTS "-G" 128# define MODULE_OPTS "-G" 129# define LINKER_FLAG_PREFIX "-Wl," 130# define NEED_SNPRINTF 131#endif 132 133#if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX) 134# define SHELL_CMD "/usr/bin/sh" 135# define DYNAMIC_LIB_EXT "so" 136# define MODULE_LIB_EXT "so" 137# define STATIC_LIB_EXT "a" 138# define OBJECT_EXT "o" 139# define LIBRARIAN "ar" 140# define LIBRARIAN_OPTS "cr" 141# define RPATH "-Brpath" 142# define SHARED_OPTS "-G" 143# define MODULE_OPTS "-G" 144# define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym" 145# define LINKER_FLAG_PREFIX "-Wl," 146# define NEED_SNPRINTF 147# define LD_RUN_PATH "LD_RUN_PATH" 148# define LD_LIBRARY_PATH "LD_LIBRARY_PATH" 149#endif 150 151#if defined(__MINGW32__) 152# define SHELL_CMD "sh" 153# define DYNAMIC_LIB_EXT "dll" 154# define MODULE_LIB_EXT "dll" 155# define STATIC_LIB_EXT "a" 156# define OBJECT_EXT "o" 157# define LIBRARIAN "ar" 158# define LIBRARIAN_OPTS "cr" 159# define RANLIB "ranlib" 160# define LINKER_FLAG_PREFIX "-Wl," 161# define SHARED_OPTS "-shared" 162# define MODULE_OPTS "-shared" 163# define MKDIR_NO_UMASK 164# define EXE_EXT ".exe" 165#endif 166 167#ifndef SHELL_CMD 168#error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform. 169#endif 170 171#ifdef NEED_SNPRINTF 172#include <stdarg.h> 173#endif 174 175#ifdef __EMX__ 176#include <process.h> 177#endif 178 179#ifndef PATH_MAX 180#define PATH_MAX 1024 181#endif 182 183 184/* We want to say we are libtool 1.4 for shlibtool compatibility. */ 185#define VERSION "1.4" 186 187enum tool_mode_t { 188 mUnknown, 189 mCompile, 190 mLink, 191 mInstall, 192}; 193 194enum output_t { 195 otGeneral, 196 otObject, 197 otProgram, 198 otLibrary, 199 otStaticLibraryOnly, 200 otDynamicLibraryOnly, 201 otModule, 202}; 203 204enum pic_mode_e { 205 pic_UNKNOWN, 206 pic_PREFER, 207 pic_AVOID, 208}; 209 210enum shared_mode_e { 211 share_UNSET, 212 share_STATIC, 213 share_SHARED, 214}; 215 216enum lib_type { 217 type_UNKNOWN, 218 type_DYNAMIC_LIB, 219 type_STATIC_LIB, 220 type_MODULE_LIB, 221 type_OBJECT, 222}; 223 224typedef struct { 225 const char **vals; 226 int num; 227} count_chars; 228 229typedef struct { 230 const char *normal; 231 const char *install; 232} library_name; 233 234typedef struct { 235 count_chars *normal; 236 count_chars *install; 237 count_chars *dependencies; 238} library_opts; 239 240typedef struct { 241 int silent; 242 enum shared_mode_e shared; 243 int export_all; 244 int dry_run; 245 enum pic_mode_e pic_mode; 246 int export_dynamic; 247 int no_install; 248} options_t; 249 250typedef struct { 251 enum tool_mode_t mode; 252 enum output_t output; 253 options_t options; 254 255 char *output_name; 256 char *fake_output_name; 257 char *basename; 258 259 const char *install_path; 260 const char *compiler; 261 const char *program; 262 count_chars *program_opts; 263 264 count_chars *arglist; 265 count_chars *tmp_dirs; 266 count_chars *obj_files; 267 count_chars *dep_rpaths; 268 count_chars *rpaths; 269 270 library_name static_name; 271 library_name shared_name; 272 library_name module_name; 273 274 library_opts static_opts; 275 library_opts shared_opts; 276 277 const char *version_info; 278 const char *undefined_flag; 279} command_t; 280 281#ifdef RPATH 282void add_rpath(count_chars *cc, const char *path); 283#endif 284 285#if defined(NEED_SNPRINTF) 286/* Write at most n characters to the buffer in str, return the 287 * number of chars written or -1 if the buffer would have been 288 * overflowed. 289 * 290 * This is portable to any POSIX-compliant system has /dev/null 291 */ 292static FILE *f=NULL; 293static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) 294{ 295 int res; 296 297 if (f == NULL) 298 f = fopen("/dev/null","w"); 299 if (f == NULL) 300 return -1; 301 302 setvbuf( f, str, _IOFBF, n ); 303 304 res = vfprintf( f, fmt, ap ); 305 306 if ( res > 0 && res < n ) { 307 res = vsprintf( str, fmt, ap ); 308 } 309 return res; 310} 311static int snprintf( char *str, size_t n, const char *fmt, ... ) 312{ 313 va_list ap; 314 int res; 315 316 va_start( ap, fmt ); 317 res = vsnprintf( str, n, fmt, ap ); 318 va_end( ap ); 319 return res; 320} 321#endif 322 323void init_count_chars(count_chars *cc) 324{ 325 cc->vals = (const char**)malloc(PATH_MAX*sizeof(char*)); 326 cc->num = 0; 327} 328 329void clear_count_chars(count_chars *cc) 330{ 331 int i; 332 for (i = 0; i < cc->num; i++) { 333 cc->vals[i] = 0; 334 } 335 336 cc->num = 0; 337} 338 339void push_count_chars(count_chars *cc, const char *newval) 340{ 341 cc->vals[cc->num++] = newval; 342} 343 344void pop_count_chars(count_chars *cc) 345{ 346 cc->num--; 347} 348 349void insert_count_chars(count_chars *cc, const char *newval, int position) 350{ 351 int i; 352 353 for (i = cc->num; i > position; i--) { 354 cc->vals[i] = cc->vals[i-1]; 355 } 356 357 cc->vals[position] = newval; 358 cc->num++; 359} 360 361void append_count_chars(count_chars *cc, count_chars *cctoadd) 362{ 363 int i; 364 for (i = 0; i < cctoadd->num; i++) { 365 if (cctoadd->vals[i]) { 366 push_count_chars(cc, cctoadd->vals[i]); 367 } 368 } 369} 370 371const char *flatten_count_chars(count_chars *cc, int space) 372{ 373 int i, size; 374 char *newval; 375 376 size = 0; 377 for (i = 0; i < cc->num; i++) { 378 if (cc->vals[i]) { 379 size += strlen(cc->vals[i]) + 1; 380 if (space) { 381 size++; 382 } 383 } 384 } 385 386 newval = (char*)malloc(size + 1); 387 newval[0] = 0; 388 389 for (i = 0; i < cc->num; i++) { 390 if (cc->vals[i]) { 391 strcat(newval, cc->vals[i]); 392 if (space) { 393 strcat(newval, " "); 394 } 395 } 396 } 397 398 return newval; 399} 400 401char *shell_esc(const char *str) 402{ 403 int in_quote = 0; 404 char *cmd; 405 unsigned char *d; 406 const unsigned char *s; 407 408 cmd = (char *)malloc(2 * strlen(str) + 3); 409 d = (unsigned char *)cmd; 410 s = (const unsigned char *)str; 411 412#ifdef __MINGW32__ 413 *d++ = '\"'; 414#endif 415 416 for (; *s; ++s) { 417 if (*s == '"') { 418 *d++ = '\\'; 419 in_quote++; 420 } 421 else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) { 422 *d++ = '\\'; 423 } 424 *d++ = *s; 425 } 426 427#ifdef __MINGW32__ 428 *d++ = '\"'; 429#endif 430 431 *d = '\0'; 432 return cmd; 433} 434 435int external_spawn(command_t *cmd, const char *file, const char **argv) 436{ 437 if (!cmd->options.silent) { 438 const char **argument = argv; 439 printf("Executing: "); 440 while (*argument) { 441 printf("%s ", *argument); 442 argument++; 443 } 444 puts(""); 445 } 446 447 if (cmd->options.dry_run) { 448 return 0; 449 } 450#if defined(__EMX__) || defined(__MINGW32__) 451 return spawnvp(P_WAIT, argv[0], argv); 452#else 453 { 454 pid_t pid; 455 pid = fork(); 456 if (pid == 0) { 457 return execvp(argv[0], (char**)argv); 458 } 459 else { 460 int statuscode; 461 waitpid(pid, &statuscode, 0); 462 if (WIFEXITED(statuscode)) { 463 return WEXITSTATUS(statuscode); 464 } 465 return 0; 466 } 467 } 468#endif 469} 470 471int run_command(command_t *cmd_data, count_chars *cc) 472{ 473 char *command; 474 const char *spawn_args[4]; 475 count_chars tmpcc; 476 477 init_count_chars(&tmpcc); 478 479 if (cmd_data->program) { 480 push_count_chars(&tmpcc, cmd_data->program); 481 } 482 483 append_count_chars(&tmpcc, cmd_data->program_opts); 484 485 append_count_chars(&tmpcc, cc); 486 487 command = shell_esc(flatten_count_chars(&tmpcc, 1)); 488 489 spawn_args[0] = SHELL_CMD; 490 spawn_args[1] = "-c"; 491 spawn_args[2] = command; 492 spawn_args[3] = NULL; 493 return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args); 494} 495 496/* 497 * print configuration 498 * shlibpath_var is used in configure. 499 */ 500void print_config() 501{ 502#ifdef LD_RUN_PATH 503 printf("runpath_var=%s\n", LD_RUN_PATH); 504#endif 505#ifdef LD_LIBRARY_PATH 506 printf("shlibpath_var=%s\n", LD_LIBRARY_PATH); 507#endif 508#ifdef SHELL_CMD 509 printf("SHELL=\"%s\"\n", SHELL_CMD); 510#endif 511} 512/* 513 * Add a directory to the runtime library search path. 514 */ 515void add_runtimedirlib(char *arg, command_t *cmd_data) 516{ 517#ifdef RPATH 518 add_rpath(cmd_data->shared_opts.dependencies, arg); 519#else 520#endif 521} 522 523int parse_long_opt(char *arg, command_t *cmd_data) 524{ 525 char *equal_pos = strchr(arg, '='); 526 char var[50]; 527 char value[500]; 528 529 if (equal_pos) { 530 strncpy(var, arg, equal_pos - arg); 531 var[equal_pos - arg] = 0; 532 strcpy(value, equal_pos + 1); 533 } else { 534 strcpy(var, arg); 535 } 536 537 if (strcmp(var, "silent") == 0) { 538 cmd_data->options.silent = 1; 539 } else if (strcmp(var, "mode") == 0) { 540 if (strcmp(value, "compile") == 0) { 541 cmd_data->mode = mCompile; 542 cmd_data->output = otObject; 543 } 544 545 if (strcmp(value, "link") == 0) { 546 cmd_data->mode = mLink; 547 cmd_data->output = otLibrary; 548 } 549 550 if (strcmp(value, "install") == 0) { 551 cmd_data->mode = mInstall; 552 } 553 } else if (strcmp(var, "shared") == 0) { 554 if (cmd_data->mode == mLink) { 555 cmd_data->output = otDynamicLibraryOnly; 556 } 557 cmd_data->options.shared = share_SHARED; 558 } else if (strcmp(var, "export-all") == 0) { 559 cmd_data->options.export_all = 1; 560 } else if (strcmp(var, "dry-run") == 0) { 561 printf("Dry-run mode on!\n"); 562 cmd_data->options.dry_run = 1; 563 } else if (strcmp(var, "version") == 0) { 564 printf("Version " VERSION "\n"); 565 } else if (strcmp(var, "help") == 0) { 566 printf("Sorry. No help available.\n"); 567 } else if (strcmp(var, "config") == 0) { 568 print_config(); 569 } else if (strcmp(var, "tag") == 0) { 570 if (strcmp(value, "CC") == 0) { 571 /* Do nothing. */ 572 } 573 if (strcmp(value, "CXX") == 0) { 574 /* Do nothing. */ 575 } 576 } else { 577 return 0; 578 } 579 580 return 1; 581} 582 583/* Return 1 if we eat it. */ 584int parse_short_opt(char *arg, command_t *cmd_data) 585{ 586 if (strcmp(arg, "export-dynamic") == 0) { 587 cmd_data->options.export_dynamic = 1; 588 return 1; 589 } 590 591 if (strcmp(arg, "module") == 0) { 592 cmd_data->output = otModule; 593 return 1; 594 } 595 596 if (strcmp(arg, "shared") == 0) { 597 if (cmd_data->mode == mLink) { 598 cmd_data->output = otDynamicLibraryOnly; 599 } 600 cmd_data->options.shared = share_SHARED; 601 return 1; 602 } 603 604 if (strcmp(arg, "Zexe") == 0) { 605 return 1; 606 } 607 608 if (strcmp(arg, "avoid-version") == 0) { 609 return 1; 610 } 611 612 if (strcmp(arg, "prefer-pic") == 0) { 613 cmd_data->options.pic_mode = pic_PREFER; 614 return 1; 615 } 616 617 if (strcmp(arg, "prefer-non-pic") == 0) { 618 cmd_data->options.pic_mode = pic_AVOID; 619 return 1; 620 } 621 622 if (strcmp(arg, "static") == 0) { 623 cmd_data->options.shared = share_STATIC; 624 return 1; 625 } 626 627 if (cmd_data->mode == mLink) { 628 if (strcmp(arg, "no-install") == 0) { 629 cmd_data->options.no_install = 1; 630 return 1; 631 } 632 if (arg[0] == 'L' || arg[0] == 'l') { 633 /* Hack... */ 634 arg--; 635 push_count_chars(cmd_data->shared_opts.dependencies, arg); 636 return 1; 637 } else if (arg[0] == 'R' && arg[1]) { 638 /* -Rdir Add dir to runtime library search path. */ 639 add_runtimedirlib(&arg[1], cmd_data); 640 return 1; 641 } 642 } 643 return 0; 644} 645 646char *truncate_dll_name(char *path) 647{ 648 /* Cut DLL name down to 8 characters after removing any mod_ prefix */ 649 char *tmppath = strdup(path); 650 char *newname = strrchr(tmppath, '/') + 1; 651 char *ext = strrchr(tmppath, '.'); 652 int len; 653 654 if (ext == NULL) 655 return tmppath; 656 657 len = ext - newname; 658 659 if (strncmp(newname, "mod_", 4) == 0) { 660 strcpy(newname, newname + 4); 661 len -= 4; 662 } 663 664 if (len > 8) { 665 strcpy(newname + 8, strchr(newname, '.')); 666 } 667 668 return tmppath; 669} 670 671long safe_strtol(const char *nptr, const char **endptr, int base) 672{ 673 long rv; 674 675 errno = 0; 676 677 rv = strtol(nptr, (char**)endptr, 10); 678 679 if (errno == ERANGE) { 680 return 0; 681 } 682 683 return rv; 684} 685 686void safe_mkdir(const char *path) 687{ 688 mode_t old_umask; 689 690 old_umask = umask(0); 691 umask(old_umask); 692 693#ifdef MKDIR_NO_UMASK 694 mkdir(path); 695#else 696 mkdir(path, ~old_umask); 697#endif 698} 699 700/* returns just a file's name without the path */ 701const char *jlibtool_basename(const char *fullpath) 702{ 703 const char *name = strrchr(fullpath, '/'); 704 705 if (name == NULL) { 706 name = strrchr(fullpath, '\\'); 707 } 708 709 if (name == NULL) { 710 name = fullpath; 711 } else { 712 name++; 713 } 714 715 return name; 716} 717 718/* returns just a file's name without path or extension */ 719const char *nameof(const char *fullpath) 720{ 721 const char *name; 722 const char *ext; 723 724 name = jlibtool_basename(fullpath); 725 ext = strrchr(name, '.'); 726 727 if (ext) { 728 char *trimmed; 729 trimmed = malloc(ext - name + 1); 730 strncpy(trimmed, name, ext - name); 731 trimmed[ext-name] = 0; 732 return trimmed; 733 } 734 735 return name; 736} 737 738/* version_info is in the form of MAJOR:MINOR:PATCH */ 739const char *darwin_dynamic_link_function(const char *version_info) 740{ 741 char *newarg; 742 long major, minor, patch; 743 744 major = 0; 745 minor = 0; 746 patch = 0; 747 748 if (version_info) { 749 major = safe_strtol(version_info, &version_info, 10); 750 751 if (version_info) { 752 if (version_info[0] == ':') { 753 version_info++; 754 } 755 756 minor = safe_strtol(version_info, &version_info, 10); 757 758 if (version_info) { 759 if (version_info[0] == ':') { 760 version_info++; 761 } 762 763 patch = safe_strtol(version_info, &version_info, 10); 764 765 } 766 } 767 } 768 769 /* Avoid -dylib_compatibility_version must be greater than zero errors. */ 770 if (major == 0) { 771 major = 1; 772 } 773 newarg = (char*)malloc(100); 774 snprintf(newarg, 99, 775 "-compatibility_version %ld -current_version %ld.%ld", 776 major, major, minor); 777 778 return newarg; 779} 780 781/* genlib values 782 * 0 - static 783 * 1 - dynamic 784 * 2 - module 785 */ 786char *gen_library_name(const char *name, int genlib) 787{ 788 char *newarg, *newext; 789 790 newarg = (char *)malloc(strlen(name) + 11); 791 strcpy(newarg, ".libs/"); 792 793 if (genlib == 2 && strncmp(name, "lib", 3) == 0) { 794 name += 3; 795 } 796 797 if (genlib == 2) { 798 strcat(newarg, jlibtool_basename(name)); 799 } 800 else { 801 strcat(newarg, name); 802 } 803 804 newext = strrchr(newarg, '.') + 1; 805 806 switch (genlib) { 807 case 0: 808 strcpy(newext, STATIC_LIB_EXT); 809 break; 810 case 1: 811 strcpy(newext, DYNAMIC_LIB_EXT); 812 break; 813 case 2: 814 strcpy(newext, MODULE_LIB_EXT); 815 break; 816 } 817 818 return newarg; 819} 820 821/* genlib values 822 * 0 - static 823 * 1 - dynamic 824 * 2 - module 825 */ 826char *gen_install_name(const char *name, int genlib) 827{ 828 struct stat sb; 829 char *newname; 830 int rv; 831 832 newname = gen_library_name(name, genlib); 833 834 /* Check if it exists. If not, return NULL. */ 835 rv = stat(newname, &sb); 836 837 if (rv) { 838 return NULL; 839 } 840 841 return newname; 842} 843 844char *check_object_exists(command_t *cmd, const char *arg, int arglen) 845{ 846 char *newarg, *ext; 847 int pass, rv; 848 849 newarg = (char *)malloc(arglen + 10); 850 memcpy(newarg, arg, arglen); 851 newarg[arglen] = 0; 852 ext = newarg + arglen; 853 854 pass = 0; 855 856 do { 857 struct stat sb; 858 859 switch (pass) { 860 case 0: 861 strcpy(ext, OBJECT_EXT); 862 break; 863/* 864 case 1: 865 strcpy(ext, NO_PIC_EXT); 866 break; 867*/ 868 default: 869 break; 870 } 871 872 if (!cmd->options.silent) { 873 printf("Checking (obj): %s\n", newarg); 874 } 875 rv = stat(newarg, &sb); 876 } 877 while (rv != 0 && ++pass < 1); 878 879 if (rv == 0) { 880 if (pass == 1) { 881 cmd->options.pic_mode = pic_AVOID; 882 } 883 return newarg; 884 } 885 886 return NULL; 887} 888 889/* libdircheck values: 890 * 0 - no .libs suffix 891 * 1 - .libs suffix 892 */ 893char *check_library_exists(command_t *cmd, const char *arg, int pathlen, 894 int libdircheck, enum lib_type *libtype) 895{ 896 char *newarg, *ext; 897 int pass, rv, newpathlen; 898 899 newarg = (char *)malloc(strlen(arg) + 10); 900 strcpy(newarg, arg); 901 newarg[pathlen] = 0; 902 903 newpathlen = pathlen; 904 if (libdircheck) { 905 strcat(newarg, ".libs/"); 906 newpathlen += sizeof(".libs/") - 1; 907 } 908 909 strcpy(newarg+newpathlen, arg+pathlen); 910 ext = strrchr(newarg, '.') + 1; 911 912 pass = 0; 913 914 do { 915 struct stat sb; 916 917 switch (pass) { 918 case 0: 919 if (cmd->options.pic_mode != pic_AVOID && 920 cmd->options.shared != share_STATIC) { 921 strcpy(ext, DYNAMIC_LIB_EXT); 922 *libtype = type_DYNAMIC_LIB; 923 break; 924 } 925 pass = 1; 926 /* Fall through */ 927 case 1: 928 strcpy(ext, STATIC_LIB_EXT); 929 *libtype = type_STATIC_LIB; 930 break; 931 case 2: 932 strcpy(ext, MODULE_LIB_EXT); 933 *libtype = type_MODULE_LIB; 934 break; 935 case 3: 936 strcpy(ext, OBJECT_EXT); 937 *libtype = type_OBJECT; 938 break; 939 default: 940 *libtype = type_UNKNOWN; 941 break; 942 } 943 944 if (!cmd->options.silent) { 945 printf("Checking (lib): %s\n", newarg); 946 } 947 rv = stat(newarg, &sb); 948 } 949 while (rv != 0 && ++pass < 4); 950 951 if (rv == 0) { 952 return newarg; 953 } 954 955 return NULL; 956} 957 958char * load_install_path(const char *arg) 959{ 960 FILE *f; 961 char *path; 962 963 path = malloc(PATH_MAX); 964 965 f = fopen(arg,"r"); 966 if (f == NULL) { 967 return NULL; 968 } 969 fgets(path, PATH_MAX, f); 970 fclose(f); 971 if (path[strlen(path)-1] == '\n') { 972 path[strlen(path)-1] = '\0'; 973 } 974 /* Check that we have an absolute path. 975 * Otherwise the file could be a GNU libtool file. 976 */ 977 if (path[0] != '/') { 978 return NULL; 979 } 980 return path; 981} 982 983char * load_noinstall_path(const char *arg, int pathlen) 984{ 985 char *newarg, *expanded_path; 986 int newpathlen; 987 988 newarg = (char *)malloc(strlen(arg) + 10); 989 strcpy(newarg, arg); 990 newarg[pathlen] = 0; 991 992 newpathlen = pathlen; 993 strcat(newarg, ".libs"); 994 newpathlen += sizeof(".libs") - 1; 995 newarg[newpathlen] = 0; 996 997#ifdef HAS_REALPATH 998 expanded_path = malloc(PATH_MAX); 999 expanded_path = realpath(newarg, expanded_path); 1000 /* Uh, oh. There was an error. Fall back on our first guess. */ 1001 if (!expanded_path) { 1002 expanded_path = newarg; 1003 } 1004#else 1005 /* We might get ../ or something goofy. Oh, well. */ 1006 expanded_path = newarg; 1007#endif 1008 1009 return expanded_path; 1010} 1011 1012void add_dynamic_link_opts(command_t *cmd_data, count_chars *args) 1013{ 1014#ifdef DYNAMIC_LINK_OPTS 1015 if (cmd_data->options.pic_mode != pic_AVOID) { 1016 if (!cmd_data->options.silent) { 1017 printf("Adding: %s\n", DYNAMIC_LINK_OPTS); 1018 } 1019 push_count_chars(args, DYNAMIC_LINK_OPTS); 1020 if (cmd_data->undefined_flag) { 1021 push_count_chars(args, "-undefined"); 1022#if defined(__APPLE__) 1023 /* -undefined dynamic_lookup is used by the bundled Python in 1024 * 10.4, but if we don't set MACOSX_DEPLOYMENT_TARGET to 10.3+, 1025 * we'll get a linker error if we pass this flag. 1026 */ 1027 if (strcasecmp(cmd_data->undefined_flag, 1028 "dynamic_lookup") == 0) { 1029 insert_count_chars(cmd_data->program_opts, 1030 "MACOSX_DEPLOYMENT_TARGET=10.3", 0); 1031 } 1032#endif 1033 push_count_chars(args, cmd_data->undefined_flag); 1034 } 1035 else { 1036#ifdef DYNAMIC_LINK_UNDEFINED 1037 if (!cmd_data->options.silent) { 1038 printf("Adding: %s\n", DYNAMIC_LINK_UNDEFINED); 1039 } 1040 push_count_chars(args, DYNAMIC_LINK_UNDEFINED); 1041#endif 1042 } 1043 } 1044#endif 1045} 1046 1047/* Read the final install location and add it to runtime library search path. */ 1048#ifdef RPATH 1049void add_rpath(count_chars *cc, const char *path) 1050{ 1051 int size = 0; 1052 char *tmp; 1053 1054#ifdef LINKER_FLAG_PREFIX 1055 size = strlen(LINKER_FLAG_PREFIX); 1056#endif 1057 size = size + strlen(path) + strlen(RPATH) + 2; 1058 tmp = malloc(size); 1059 if (tmp == NULL) { 1060 return; 1061 } 1062#ifdef LINKER_FLAG_PREFIX 1063 strcpy(tmp, LINKER_FLAG_PREFIX); 1064 strcat(tmp, RPATH); 1065#else 1066 strcpy(tmp, RPATH); 1067#endif 1068#ifndef LINKER_FLAG_NO_EQUALS 1069 strcat(tmp, "="); 1070#endif 1071 strcat(tmp, path); 1072 1073 push_count_chars(cc, tmp); 1074} 1075 1076void add_rpath_file(count_chars *cc, const char *arg) 1077{ 1078 const char *path; 1079 1080 path = load_install_path(arg); 1081 if (path) { 1082 add_rpath(cc, path); 1083 } 1084} 1085 1086void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen) 1087{ 1088 const char *path; 1089 1090 path = load_noinstall_path(arg, pathlen); 1091 if (path) { 1092 add_rpath(cc, path); 1093 } 1094} 1095#endif 1096 1097#ifdef DYNAMIC_LINK_NO_INSTALL 1098void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen, 1099 int extlen) 1100{ 1101 const char *install_path, *current_path, *name; 1102 char *exp_argument; 1103 int i_p_len, c_p_len, name_len, dyext_len, cur_len; 1104 1105 install_path = load_install_path(arg); 1106 current_path = load_noinstall_path(arg, pathlen); 1107 1108 if (!install_path || !current_path) { 1109 return; 1110 } 1111 1112 push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL); 1113 1114 i_p_len = strlen(install_path); 1115 c_p_len = strlen(current_path); 1116 1117 name = arg+pathlen; 1118 name_len = extlen-pathlen; 1119 dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1; 1120 1121 /* No, we need to replace the extension. */ 1122 exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) + 1123 (dyext_len*2) + 2); 1124 1125 cur_len = 0; 1126 strcpy(exp_argument, install_path); 1127 cur_len += i_p_len; 1128 exp_argument[cur_len++] = '/'; 1129 strncpy(exp_argument+cur_len, name, extlen-pathlen); 1130 cur_len += name_len; 1131 strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT); 1132 cur_len += dyext_len; 1133 exp_argument[cur_len++] = ':'; 1134 strcpy(exp_argument+cur_len, current_path); 1135 cur_len += c_p_len; 1136 exp_argument[cur_len++] = '/'; 1137 strncpy(exp_argument+cur_len, name, extlen-pathlen); 1138 cur_len += name_len; 1139 strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT); 1140 cur_len += dyext_len; 1141 1142 push_count_chars(cc, exp_argument); 1143} 1144#endif 1145 1146/* use -L -llibname to allow to use installed libraries */ 1147void add_minus_l(count_chars *cc, const char *arg) 1148{ 1149 char *newarg; 1150 char *name = strrchr(arg, '/'); 1151 char *file = strrchr(arg, '.'); 1152 char *lib = strstr(name, "lib"); 1153 1154 if (name !=NULL && file != NULL && lib == name+1) { 1155 *name = '\0'; 1156 *file = '\0'; 1157 file = name; 1158 file = file+4; 1159 push_count_chars(cc, "-L"); 1160 push_count_chars(cc, arg); 1161 /* we need one argument like -lapr-1 */ 1162 newarg = malloc(strlen(file) + 3); 1163 strcpy(newarg, "-l"); 1164 strcat(newarg, file); 1165 push_count_chars(cc, newarg); 1166 } else { 1167 push_count_chars(cc, arg); 1168 } 1169} 1170 1171void add_linker_flag_prefix(count_chars *cc, const char *arg) 1172{ 1173#ifndef LINKER_FLAG_PREFIX 1174 push_count_chars(cc, arg); 1175#else 1176 char *newarg; 1177 newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1); 1178 strcpy(newarg, LINKER_FLAG_PREFIX); 1179 strcat(newarg, arg); 1180 push_count_chars(cc, newarg); 1181#endif 1182} 1183 1184int explode_static_lib(command_t *cmd_data, const char *lib) 1185{ 1186 count_chars tmpdir_cc, libname_cc; 1187 const char *tmpdir, *libname; 1188 char savewd[PATH_MAX]; 1189 const char *name; 1190 DIR *dir; 1191 struct dirent *entry; 1192 const char *lib_args[4]; 1193 1194 /* Bah! */ 1195 if (cmd_data->options.dry_run) { 1196 return 0; 1197 } 1198 1199 name = jlibtool_basename(lib); 1200 1201 init_count_chars(&tmpdir_cc); 1202 push_count_chars(&tmpdir_cc, ".libs/"); 1203 push_count_chars(&tmpdir_cc, name); 1204 push_count_chars(&tmpdir_cc, ".exploded/"); 1205 tmpdir = flatten_count_chars(&tmpdir_cc, 0); 1206 1207 if (!cmd_data->options.silent) { 1208 printf("Making: %s\n", tmpdir); 1209 } 1210 safe_mkdir(tmpdir); 1211 1212 push_count_chars(cmd_data->tmp_dirs, tmpdir); 1213 1214 getcwd(savewd, sizeof(savewd)); 1215 1216 if (chdir(tmpdir) != 0) { 1217 if (!cmd_data->options.silent) { 1218 printf("Warning: could not explode %s\n", lib); 1219 } 1220 return 1; 1221 } 1222 1223 if (lib[0] == '/') { 1224 libname = lib; 1225 } 1226 else { 1227 init_count_chars(&libname_cc); 1228 push_count_chars(&libname_cc, "../../"); 1229 push_count_chars(&libname_cc, lib); 1230 libname = flatten_count_chars(&libname_cc, 0); 1231 } 1232 1233 lib_args[0] = LIBRARIAN; 1234 lib_args[1] = "x"; 1235 lib_args[2] = libname; 1236 lib_args[3] = NULL; 1237 1238 external_spawn(cmd_data, LIBRARIAN, lib_args); 1239 1240 chdir(savewd); 1241 dir = opendir(tmpdir); 1242 1243 while ((entry = readdir(dir)) != NULL) { 1244#if defined(__APPLE__) && defined(RANLIB) 1245 /* Apple inserts __.SYMDEF which isn't needed. 1246 * Leopard (10.5+) can also add '__.SYMDEF SORTED' which isn't 1247 * much fun either. Just skip them. 1248 */ 1249 if (strstr(entry->d_name, "__.SYMDEF") != NULL) { 1250 continue; 1251 } 1252#endif 1253 if (entry->d_name[0] != '.') { 1254 push_count_chars(&tmpdir_cc, entry->d_name); 1255 name = flatten_count_chars(&tmpdir_cc, 0); 1256 if (!cmd_data->options.silent) { 1257 printf("Adding: %s\n", name); 1258 } 1259 push_count_chars(cmd_data->obj_files, name); 1260 pop_count_chars(&tmpdir_cc); 1261 } 1262 } 1263 1264 closedir(dir); 1265 return 0; 1266} 1267 1268int parse_input_file_name(char *arg, command_t *cmd_data) 1269{ 1270 char *ext = strrchr(arg, '.'); 1271 char *name = strrchr(arg, '/'); 1272 int pathlen; 1273 enum lib_type libtype; 1274 char *newarg; 1275 1276 if (!ext) { 1277 return 0; 1278 } 1279 1280 ext++; 1281 1282 if (name == NULL) { 1283 name = strrchr(arg, '\\'); 1284 1285 if (name == NULL) { 1286 name = arg; 1287 } else { 1288 name++; 1289 } 1290 } else { 1291 name++; 1292 } 1293 1294 pathlen = name - arg; 1295 1296 if (strcmp(ext, "lo") == 0) { 1297 newarg = check_object_exists(cmd_data, arg, ext - arg); 1298 if (!newarg) { 1299 printf("Can not find suitable object file for %s\n", arg); 1300 exit(1); 1301 } 1302 if (cmd_data->mode != mLink) { 1303 push_count_chars(cmd_data->arglist, newarg); 1304 } 1305 else { 1306 push_count_chars(cmd_data->obj_files, newarg); 1307 } 1308 return 1; 1309 } 1310 1311 if (strcmp(ext, "la") == 0) { 1312 switch (cmd_data->mode) { 1313 case mLink: 1314 /* Try the .libs dir first! */ 1315 newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype); 1316 if (!newarg) { 1317 /* Try the normal dir next. */ 1318 newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype); 1319 if (!newarg) { 1320 printf("Can not find suitable library for %s\n", arg); 1321 exit(1); 1322 } 1323 } 1324 1325 /* It is not ok to just add the file: a library may added with: 1326 1 - -L path library_name. (For *.so in Linux). 1327 2 - library_name. 1328 */ 1329#ifdef ADD_MINUS_L 1330 if (libtype == type_DYNAMIC_LIB) { 1331 add_minus_l(cmd_data->shared_opts.dependencies, newarg); 1332 } else if (cmd_data->output == otLibrary && 1333 libtype == type_STATIC_LIB) { 1334 explode_static_lib(cmd_data, newarg); 1335 } else { 1336 push_count_chars(cmd_data->shared_opts.dependencies, newarg); 1337 } 1338#else 1339 if (cmd_data->output == otLibrary && libtype == type_STATIC_LIB) { 1340 explode_static_lib(cmd_data, newarg); 1341 } 1342 else { 1343 push_count_chars(cmd_data->shared_opts.dependencies, newarg); 1344 } 1345#endif 1346 if (libtype == type_DYNAMIC_LIB) { 1347 if (cmd_data->options.no_install) { 1348#ifdef RPATH 1349 add_rpath_noinstall(cmd_data->shared_opts.dependencies, 1350 arg, pathlen); 1351#endif 1352#ifdef DYNAMIC_LINK_NO_INSTALL 1353 /* 1354 * This doesn't work as Darwin's linker has no way to 1355 * override at link-time the search paths for a 1356 * non-installed library. 1357 */ 1358 /* 1359 add_dylink_noinstall(cmd_data->shared_opts.dependencies, 1360 arg, pathlen, ext - arg); 1361 */ 1362#endif 1363 } 1364 else { 1365#ifdef RPATH 1366 add_rpath_file(cmd_data->shared_opts.dependencies, arg); 1367#endif 1368 } 1369 } 1370 break; 1371 case mInstall: 1372 /* If we've already recorded a library to install, we're most 1373 * likely getting the .la file that we want to install as. 1374 * The problem is that we need to add it as the directory, 1375 * not the .la file itself. Otherwise, we'll do odd things. 1376 */ 1377 if (cmd_data->output == otLibrary) { 1378 arg[pathlen] = '\0'; 1379 push_count_chars(cmd_data->arglist, arg); 1380 } 1381 else { 1382 cmd_data->output = otLibrary; 1383 cmd_data->output_name = arg; 1384 cmd_data->static_name.install = gen_install_name(arg, 0); 1385 cmd_data->shared_name.install = gen_install_name(arg, 1); 1386 cmd_data->module_name.install = gen_install_name(arg, 2); 1387 } 1388 break; 1389 default: 1390 break; 1391 } 1392 return 1; 1393 } 1394 1395 if (strcmp(ext, "c") == 0) { 1396 /* If we don't already have an idea what our output name will be. */ 1397 if (cmd_data->basename == NULL) { 1398 cmd_data->basename = (char *)malloc(strlen(arg) + 4); 1399 strcpy(cmd_data->basename, arg); 1400 strcpy(strrchr(cmd_data->basename, '.') + 1, "lo"); 1401 1402 cmd_data->fake_output_name = strrchr(cmd_data->basename, '/'); 1403 if (cmd_data->fake_output_name) { 1404 cmd_data->fake_output_name++; 1405 } 1406 else { 1407 cmd_data->fake_output_name = cmd_data->basename; 1408 } 1409 } 1410 } 1411 1412 return 0; 1413} 1414 1415int parse_output_file_name(char *arg, command_t *cmd_data) 1416{ 1417 char *name = strrchr(arg, '/'); 1418 char *ext = strrchr(arg, '.'); 1419 char *newarg = NULL; 1420 int pathlen; 1421 1422 cmd_data->fake_output_name = arg; 1423 1424 if (name) { 1425 name++; 1426 } 1427 else { 1428 name = strrchr(arg, '\\'); 1429 1430 if (name == NULL) { 1431 name = arg; 1432 } 1433 else { 1434 name++; 1435 } 1436 } 1437 1438#ifdef EXE_EXT 1439 if (!ext || strcmp(ext, EXE_EXT) == 0) { 1440#else 1441 if (!ext) { 1442#endif 1443 cmd_data->basename = arg; 1444 cmd_data->output = otProgram; 1445#if defined(_OSD_POSIX) 1446 cmd_data->options.pic_mode = pic_AVOID; 1447#endif 1448 newarg = (char *)malloc(strlen(arg) + 5); 1449 strcpy(newarg, arg); 1450#ifdef EXE_EXT 1451 if (!ext) { 1452 strcat(newarg, EXE_EXT); 1453 } 1454#endif 1455 cmd_data->output_name = newarg; 1456 return 1; 1457 } 1458 1459 ext++; 1460 pathlen = name - arg; 1461 1462 if (strcmp(ext, "la") == 0) { 1463 assert(cmd_data->mode == mLink); 1464 1465 cmd_data->basename = arg; 1466 cmd_data->static_name.normal = gen_library_name(arg, 0); 1467 cmd_data->shared_name.normal = gen_library_name(arg, 1); 1468 cmd_data->module_name.normal = gen_library_name(arg, 2); 1469 cmd_data->static_name.install = gen_install_name(arg, 0); 1470 cmd_data->shared_name.install = gen_install_name(arg, 1); 1471 cmd_data->module_name.install = gen_install_name(arg, 2); 1472 1473#ifdef TRUNCATE_DLL_NAME 1474 if (shared) { 1475 arg = truncate_dll_name(arg); 1476 } 1477#endif 1478 1479 cmd_data->output_name = arg; 1480 return 1; 1481 } 1482 1483 if (strcmp(ext, "lo") == 0) { 1484 cmd_data->basename = arg; 1485 cmd_data->output = otObject; 1486 newarg = (char *)malloc(strlen(arg) + 2); 1487 strcpy(newarg, arg); 1488 ext = strrchr(newarg, '.') + 1; 1489 strcpy(ext, OBJECT_EXT); 1490 cmd_data->output_name = newarg; 1491 return 1; 1492 } 1493 1494 return 0; 1495} 1496 1497void parse_args(int argc, char *argv[], command_t *cmd_data) 1498{ 1499 int a; 1500 char *arg; 1501 int argused; 1502 1503 for (a = 1; a < argc; a++) { 1504 arg = argv[a]; 1505 argused = 1; 1506 1507 if (arg[0] == '-') { 1508 if (arg[1] == '-') { 1509 argused = parse_long_opt(arg + 2, cmd_data); 1510 } 1511 else { 1512 argused = parse_short_opt(arg + 1, cmd_data); 1513 } 1514 1515 /* We haven't done anything with it yet, try some of the 1516 * more complicated short opts... */ 1517 if (argused == 0 && a + 1 < argc) { 1518 if (arg[1] == 'o' && !arg[2]) { 1519 arg = argv[++a]; 1520 argused = parse_output_file_name(arg, cmd_data); 1521 } else if (strcmp(arg+1, "MT") == 0) { 1522 if (!cmd_data->options.silent) { 1523 printf("Adding: %s\n", arg); 1524 } 1525 push_count_chars(cmd_data->arglist, arg); 1526 arg = argv[++a]; 1527 if (!cmd_data->options.silent) { 1528 printf(" %s\n", arg); 1529 } 1530 push_count_chars(cmd_data->arglist, arg); 1531 argused = 1; 1532 } else if (strcmp(arg+1, "rpath") == 0) { 1533 /* Aha, we should try to link both! */ 1534 cmd_data->install_path = argv[++a]; 1535 argused = 1; 1536 } else if (strcmp(arg+1, "release") == 0) { 1537 /* Store for later deciphering */ 1538 cmd_data->version_info = argv[++a]; 1539 argused = 1; 1540 } else if (strcmp(arg+1, "version-info") == 0) { 1541 /* Store for later deciphering */ 1542 cmd_data->version_info = argv[++a]; 1543 argused = 1; 1544 } else if (strcmp(arg+1, "export-symbols-regex") == 0) { 1545 /* Skip the argument. */ 1546 ++a; 1547 argused = 1; 1548 } else if (strcmp(arg+1, "release") == 0) { 1549 /* Skip the argument. */ 1550 ++a; 1551 argused = 1; 1552 } else if (strcmp(arg+1, "undefined") == 0) { 1553 cmd_data->undefined_flag = argv[++a]; 1554 argused = 1; 1555 } else if (arg[1] == 'R' && !arg[2]) { 1556 /* -R dir Add dir to runtime library search path. */ 1557 add_runtimedirlib(argv[++a], cmd_data); 1558 argused = 1; 1559 } 1560 } 1561 } else { 1562 argused = parse_input_file_name(arg, cmd_data); 1563 } 1564 1565 if (!argused) { 1566 if (!cmd_data->options.silent) { 1567 printf("Adding: %s\n", arg); 1568 } 1569 push_count_chars(cmd_data->arglist, arg); 1570 } 1571 } 1572 1573} 1574 1575#ifdef GEN_EXPORTS 1576void generate_def_file(command_t *cmd_data) 1577{ 1578 char def_file[1024]; 1579 char implib_file[1024]; 1580 char *ext; 1581 FILE *hDef; 1582 char *export_args[1024]; 1583 int num_export_args = 0; 1584 char *cmd; 1585 int cmd_size = 0; 1586 int a; 1587 1588 if (cmd_data->output_name) { 1589 strcpy(def_file, cmd_data->output_name); 1590 strcat(def_file, ".def"); 1591 hDef = fopen(def_file, "w"); 1592 1593 if (hDef != NULL) { 1594 fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name)); 1595 fprintf(hDef, "DATA NONSHARED\n"); 1596 fprintf(hDef, "EXPORTS\n"); 1597 fclose(hDef); 1598 1599 for (a = 0; a < cmd_data->num_obj_files; a++) { 1600 cmd_size += strlen(cmd_data->obj_files[a]) + 1; 1601 } 1602 1603 cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3; 1604 cmd = (char *)malloc(cmd_size); 1605 strcpy(cmd, GEN_EXPORTS); 1606 1607 for (a=0; a < cmd_data->num_obj_files; a++) { 1608 strcat(cmd, " "); 1609 strcat(cmd, cmd_data->obj_files[a] ); 1610 } 1611 1612 strcat(cmd, ">>"); 1613 strcat(cmd, def_file); 1614 puts(cmd); 1615 export_args[num_export_args++] = SHELL_CMD; 1616 export_args[num_export_args++] = "-c"; 1617 export_args[num_export_args++] = cmd; 1618 export_args[num_export_args++] = NULL; 1619 external_spawn(cmd_data, export_args[0], (const char**)export_args); 1620 cmd_data->arglist[cmd_data->num_args++] = strdup(def_file); 1621 1622 /* Now make an import library for the dll */ 1623 num_export_args = 0; 1624 export_args[num_export_args++] = DEF2IMPLIB_CMD; 1625 export_args[num_export_args++] = "-o"; 1626 1627 strcpy(implib_file, ".libs/"); 1628 strcat(implib_file, cmd_data->basename); 1629 ext = strrchr(implib_file, '.'); 1630 1631 if (ext) 1632 *ext = 0; 1633 1634 strcat(implib_file, "."); 1635 strcat(implib_file, STATIC_LIB_EXT); 1636 1637 export_args[num_export_args++] = implib_file; 1638 export_args[num_export_args++] = def_file; 1639 export_args[num_export_args++] = NULL; 1640 external_spawn(cmd_data, export_args[0], (const char**)export_args); 1641 1642 } 1643 } 1644} 1645#endif 1646 1647const char* expand_path(const char *relpath) 1648{ 1649 char foo[PATH_MAX], *newpath; 1650 1651 getcwd(foo, PATH_MAX-1); 1652 newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2); 1653 strcpy(newpath, foo); 1654 strcat(newpath, "/"); 1655 strcat(newpath, relpath); 1656 return newpath; 1657} 1658 1659void link_fixup(command_t *c) 1660{ 1661 /* If we were passed an -rpath directive, we need to build 1662 * shared objects too. Otherwise, we should only create static 1663 * libraries. 1664 */ 1665 if (!c->install_path && (c->output == otDynamicLibraryOnly || 1666 c->output == otModule || c->output == otLibrary)) { 1667 c->output = otStaticLibraryOnly; 1668 } 1669 1670 if (c->output == otDynamicLibraryOnly || 1671 c->output == otModule || 1672 c->output == otLibrary) { 1673 1674 push_count_chars(c->shared_opts.normal, "-o"); 1675 if (c->output == otModule) { 1676 push_count_chars(c->shared_opts.normal, c->module_name.normal); 1677 } 1678 else { 1679 char *tmp; 1680 push_count_chars(c->shared_opts.normal, c->shared_name.normal); 1681#ifdef DYNAMIC_INSTALL_NAME 1682 push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME); 1683 1684 tmp = (char*)malloc(PATH_MAX); 1685 strcpy(tmp, c->install_path); 1686 strcat(tmp, strrchr(c->shared_name.normal, '/')); 1687 push_count_chars(c->shared_opts.normal, tmp); 1688#endif 1689 } 1690 1691 append_count_chars(c->shared_opts.normal, c->obj_files); 1692 append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies); 1693 1694 if (c->options.export_all) { 1695#ifdef GEN_EXPORTS 1696 generate_def_file(c); 1697#endif 1698 } 1699 } 1700 1701 if (c->output == otLibrary || c->output == otStaticLibraryOnly) { 1702 push_count_chars(c->static_opts.normal, "-o"); 1703 push_count_chars(c->static_opts.normal, c->output_name); 1704 } 1705 1706 if (c->output == otProgram) { 1707 if (c->output_name) { 1708 push_count_chars(c->arglist, "-o"); 1709 push_count_chars(c->arglist, c->output_name); 1710 append_count_chars(c->arglist, c->obj_files); 1711 append_count_chars(c->arglist, c->shared_opts.dependencies); 1712 add_dynamic_link_opts(c, c->arglist); 1713 } 1714 } 1715} 1716 1717void post_parse_fixup(command_t *cmd_data) 1718{ 1719 switch (cmd_data->mode) 1720 { 1721 case mCompile: 1722#ifdef PIC_FLAG 1723 if (cmd_data->options.pic_mode != pic_AVOID) { 1724 push_count_chars(cmd_data->arglist, PIC_FLAG); 1725 } 1726#endif 1727 if (cmd_data->output_name) { 1728 push_count_chars(cmd_data->arglist, "-o"); 1729 push_count_chars(cmd_data->arglist, cmd_data->output_name); 1730 } 1731 break; 1732 case mLink: 1733 link_fixup(cmd_data); 1734 break; 1735 case mInstall: 1736 if (cmd_data->output == otLibrary) { 1737 link_fixup(cmd_data); 1738 } 1739 default: 1740 break; 1741 } 1742 1743#if USE_OMF 1744 if (cmd_data->output == otObject || 1745 cmd_data->output == otProgram || 1746 cmd_data->output == otLibrary || 1747 cmd_data->output == otDynamicLibraryOnly) { 1748 push_count_chars(cmd_data->arglist, "-Zomf"); 1749 } 1750#endif 1751 1752 if (cmd_data->options.shared && 1753 (cmd_data->output == otObject || 1754 cmd_data->output == otLibrary || 1755 cmd_data->output == otDynamicLibraryOnly)) { 1756#ifdef SHARE_SW 1757 push_count_chars(cmd_data->arglist, SHARE_SW); 1758#endif 1759 } 1760} 1761 1762int run_mode(command_t *cmd_data) 1763{ 1764 int rv; 1765 count_chars *cctemp; 1766 1767 cctemp = (count_chars*)malloc(sizeof(count_chars)); 1768 init_count_chars(cctemp); 1769 1770 switch (cmd_data->mode) 1771 { 1772 case mCompile: 1773 rv = run_command(cmd_data, cmd_data->arglist); 1774 if (rv) { 1775 return rv; 1776 } 1777 break; 1778 case mInstall: 1779 /* Well, we'll assume it's a file going to a directory... */ 1780 /* For brain-dead install-sh based scripts, we have to repeat 1781 * the command N-times. install-sh should die. 1782 */ 1783 if (!cmd_data->output_name) { 1784 rv = run_command(cmd_data, cmd_data->arglist); 1785 if (rv) { 1786 return rv; 1787 } 1788 } 1789 if (cmd_data->output_name) { 1790 append_count_chars(cctemp, cmd_data->arglist); 1791 insert_count_chars(cctemp, 1792 cmd_data->output_name, 1793 cctemp->num - 1); 1794 rv = run_command(cmd_data, cctemp); 1795 if (rv) { 1796 return rv; 1797 } 1798 clear_count_chars(cctemp); 1799 } 1800 if (cmd_data->static_name.install) { 1801 append_count_chars(cctemp, cmd_data->arglist); 1802 insert_count_chars(cctemp, 1803 cmd_data->static_name.install, 1804 cctemp->num - 1); 1805 rv = run_command(cmd_data, cctemp); 1806 if (rv) { 1807 return rv; 1808 } 1809#if defined(__APPLE__) && defined(RANLIB) 1810 /* From the Apple libtool(1) manpage on Tiger/10.4: 1811 * ---- 1812 * With the way libraries used to be created, errors were possible 1813 * if the library was modified with ar(1) and the table of 1814 * contents was not updated by rerunning ranlib(1). Thus the 1815 * link editor, ld, warns when the modification date of a library 1816 * is more recent than the creation date of its table of 1817 * contents. Unfortunately, this means that you get the warning 1818 * even if you only copy the library. 1819 * ---- 1820 * 1821 * This means that when we install the static archive, we need to 1822 * rerun ranlib afterwards. 1823 */ 1824 const char *lib_args[3], *static_lib_name; 1825 char *tmp; 1826 size_t len1, len2; 1827 len1 = strlen(cmd_data->arglist->vals[cmd_data->arglist->num - 1]); 1828 1829 static_lib_name = jlibtool_basename(cmd_data->static_name.install); 1830 len2 = strlen(static_lib_name); 1831 1832 tmp = malloc(len1 + len2 + 2); 1833 1834 snprintf(tmp, len1 + len2 + 2, "%s/%s", 1835 cmd_data->arglist->vals[cmd_data->arglist->num - 1], 1836 static_lib_name); 1837 1838 lib_args[0] = RANLIB; 1839 lib_args[1] = tmp; 1840 lib_args[2] = NULL; 1841 external_spawn(cmd_data, RANLIB, lib_args); 1842 free(tmp); 1843#endif 1844 clear_count_chars(cctemp); 1845 } 1846 if (cmd_data->shared_name.install) { 1847 append_count_chars(cctemp, cmd_data->arglist); 1848 insert_count_chars(cctemp, 1849 cmd_data->shared_name.install, 1850 cctemp->num - 1); 1851 rv = run_command(cmd_data, cctemp); 1852 if (rv) { 1853 return rv; 1854 } 1855 clear_count_chars(cctemp); 1856 } 1857 if (cmd_data->module_name.install) { 1858 append_count_chars(cctemp, cmd_data->arglist); 1859 insert_count_chars(cctemp, 1860 cmd_data->module_name.install, 1861 cctemp->num - 1); 1862 rv = run_command(cmd_data, cctemp); 1863 if (rv) { 1864 return rv; 1865 } 1866 clear_count_chars(cctemp); 1867 } 1868 break; 1869 case mLink: 1870 if (!cmd_data->options.dry_run) { 1871 /* Check first to see if the dir already exists! */ 1872 safe_mkdir(".libs"); 1873 } 1874 1875 if (cmd_data->output == otStaticLibraryOnly || 1876 cmd_data->output == otLibrary) { 1877#ifdef RANLIB 1878 const char *lib_args[3]; 1879#endif 1880 /* Removes compiler! */ 1881 cmd_data->program = LIBRARIAN; 1882 push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS); 1883 push_count_chars(cmd_data->program_opts, 1884 cmd_data->static_name.normal); 1885 1886 rv = run_command(cmd_data, cmd_data->obj_files); 1887 if (rv) { 1888 return rv; 1889 } 1890 1891#ifdef RANLIB 1892 lib_args[0] = RANLIB; 1893 lib_args[1] = cmd_data->static_name.normal; 1894 lib_args[2] = NULL; 1895 external_spawn(cmd_data, RANLIB, lib_args); 1896#endif 1897 } 1898 1899 if (cmd_data->output == otDynamicLibraryOnly || 1900 cmd_data->output == otModule || 1901 cmd_data->output == otLibrary) { 1902 cmd_data->program = NULL; 1903 clear_count_chars(cmd_data->program_opts); 1904 1905 append_count_chars(cmd_data->program_opts, cmd_data->arglist); 1906 if (cmd_data->output == otModule) { 1907#ifdef MODULE_OPTS 1908 push_count_chars(cmd_data->program_opts, MODULE_OPTS); 1909#endif 1910 } else { 1911#ifdef SHARED_OPTS 1912 push_count_chars(cmd_data->program_opts, SHARED_OPTS); 1913#endif 1914#ifdef dynamic_link_version_func 1915 push_count_chars(cmd_data->program_opts, 1916 dynamic_link_version_func(cmd_data->version_info)); 1917#endif 1918 } 1919 add_dynamic_link_opts(cmd_data, cmd_data->program_opts); 1920 1921 rv = run_command(cmd_data, cmd_data->shared_opts.normal); 1922 if (rv) { 1923 return rv; 1924 } 1925 } 1926 if (cmd_data->output == otProgram) { 1927 rv = run_command(cmd_data, cmd_data->arglist); 1928 if (rv) { 1929 return rv; 1930 } 1931 } 1932 break; 1933 default: 1934 break; 1935 } 1936 1937 return 0; 1938} 1939 1940void cleanup_tmp_dir(const char *dirname) 1941{ 1942 DIR *dir; 1943 struct dirent *entry; 1944 char fullname[1024]; 1945 1946 dir = opendir(dirname); 1947 1948 if (dir == NULL) 1949 return; 1950 1951 while ((entry = readdir(dir)) != NULL) { 1952 if (entry->d_name[0] != '.') { 1953 strcpy(fullname, dirname); 1954 strcat(fullname, "/"); 1955 strcat(fullname, entry->d_name); 1956 remove(fullname); 1957 } 1958 } 1959 1960 rmdir(dirname); 1961} 1962 1963void cleanup_tmp_dirs(command_t *cmd_data) 1964{ 1965 int d; 1966 1967 for (d = 0; d < cmd_data->tmp_dirs->num; d++) { 1968 cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]); 1969 } 1970} 1971 1972int ensure_fake_uptodate(command_t *cmd_data) 1973{ 1974 /* FIXME: could do the stat/touch here, but nah... */ 1975 const char *touch_args[3]; 1976 1977 if (cmd_data->mode == mInstall) { 1978 return 0; 1979 } 1980 if (!cmd_data->fake_output_name) { 1981 return 0; 1982 } 1983 1984 touch_args[0] = "touch"; 1985 touch_args[1] = cmd_data->fake_output_name; 1986 touch_args[2] = NULL; 1987 return external_spawn(cmd_data, "touch", touch_args); 1988} 1989 1990/* Store the install path in the *.la file */ 1991int add_for_runtime(command_t *cmd_data) 1992{ 1993 if (cmd_data->mode == mInstall) { 1994 return 0; 1995 } 1996 if (cmd_data->output == otDynamicLibraryOnly || 1997 cmd_data->output == otLibrary) { 1998 FILE *f=fopen(cmd_data->fake_output_name,"w"); 1999 if (f == NULL) { 2000 return -1; 2001 } 2002 fprintf(f,"%s\n", cmd_data->install_path); 2003 fclose(f); 2004 return(0); 2005 } else { 2006 return(ensure_fake_uptodate(cmd_data)); 2007 } 2008} 2009 2010int main(int argc, char *argv[]) 2011{ 2012 int rc; 2013 command_t cmd_data; 2014 2015 memset(&cmd_data, 0, sizeof(cmd_data)); 2016 2017 cmd_data.options.pic_mode = pic_UNKNOWN; 2018 2019 cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars)); 2020 init_count_chars(cmd_data.program_opts); 2021 cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars)); 2022 init_count_chars(cmd_data.arglist); 2023 cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars)); 2024 init_count_chars(cmd_data.tmp_dirs); 2025 cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars)); 2026 init_count_chars(cmd_data.obj_files); 2027 cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars)); 2028 init_count_chars(cmd_data.dep_rpaths); 2029 cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars)); 2030 init_count_chars(cmd_data.rpaths); 2031 cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars)); 2032 init_count_chars(cmd_data.static_opts.normal); 2033 cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars)); 2034 init_count_chars(cmd_data.shared_opts.normal); 2035 cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars)); 2036 init_count_chars(cmd_data.shared_opts.dependencies); 2037 2038 cmd_data.mode = mUnknown; 2039 cmd_data.output = otGeneral; 2040 2041 parse_args(argc, argv, &cmd_data); 2042 post_parse_fixup(&cmd_data); 2043 2044 if (cmd_data.mode == mUnknown) { 2045 exit(0); 2046 } 2047 2048 rc = run_mode(&cmd_data); 2049 2050 if (!rc) { 2051 add_for_runtime(&cmd_data); 2052 } 2053 2054 cleanup_tmp_dirs(&cmd_data); 2055 return rc; 2056} 2057