comparison dmd/Util.d @ 22:fd4acc376c45

Implemented object file output and linking on linux.
author Robert Clipsham <robert@octarineparrot.com>
date Thu, 08 Apr 2010 04:21:03 +0100
parents 5c9b78899f5d
children cfa3747ebe4c
comparison
equal deleted inserted replaced
21:26b9f97f6162 22:fd4acc376c45
14 import std.c.string; 14 import std.c.string;
15 import std.stdio : writef, writefln, write; 15 import std.stdio : writef, writefln, write;
16 version (Windows) 16 version (Windows)
17 { 17 {
18 import std.c.process : spawnl, spawnlp; 18 import std.c.process : spawnl, spawnlp;
19 }
20 version (POSIX)
21 {
22 import core.sys.posix.unistd;
19 } 23 }
20 import core.stdc.stdlib; 24 import core.stdc.stdlib;
21 import core.stdc.ctype; 25 import core.stdc.ctype;
22 import core.stdc.stdarg; 26 import core.stdc.stdarg;
23 public import core.stdc.stdio; 27 public import core.stdc.stdio;
812 remove(toStringz(lnkfilename.toChars())); 816 remove(toStringz(lnkfilename.toChars()));
813 ///delete lnkfilename; 817 ///delete lnkfilename;
814 } 818 }
815 return status; 819 return status;
816 } else version (POSIX) {/// linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 820 } else version (POSIX) {/// linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
817 assert(false, "Unimplemented");
818 /+
819 pid_t childpid; 821 pid_t childpid;
820 int i; 822 int i;
821 int status; 823 int status;
822 824
823 // Build argv[] 825 // Build argv[]
824 Array argv; 826 Array argv = new Array();
825 827
826 const char *cc = getenv("CC"); 828 const(char)* cc = core.stdc.stdlib.getenv("CC");
827 if (!cc) 829 if (!cc)
828 cc = "gcc"; 830 cc = "gcc";
829 argv.push((void *)cc); 831 argv.push(cast(void *)cc);
830 argv.insert(1, global.params.objfiles); 832 Array objfiles = new Array;
833 for( i = 0; i < global.params.objfiles.dim; i++ )
834 { string str = (cast(String)global.params.objfiles.data[i]).str;
835 objfiles.push(cast(void*)toStringz(str));
836 }
837 argv.insert(1, objfiles);
831 838
832 // None of that a.out stuff. Use explicit exe file name, or 839 // None of that a.out stuff. Use explicit exe file name, or
833 // generate one from name of first source file. 840 // generate one from name of first source file.
834 argv.push((void *)"-o"); 841 argv.push(cast(void *)cast(char*)"-o");
835 if (global.params.exefile) 842 if (global.params.exefile)
836 { 843 {
837 argv.push(global.params.exefile); 844 argv.push(cast(void*)toStringz(global.params.exefile));
838 } 845 }
839 else 846 else
840 { // Generate exe file name from first obj name 847 { // Generate exe file name from first obj name
841 char *n = (char *)global.params.objfiles.data[0]; 848 string n = (cast(String)global.params.objfiles.data[0]).str;
842 char *e;
843 char *ex;
844
845 n = FileName.name(n); 849 n = FileName.name(n);
846 e = FileName.ext(n); 850 string e = FileName.ext(n);
847 if (e) 851 string ex = e ? n[0..$-(e.length+1)] : "a.out";
848 { 852
849 e--; // back up over '.' 853 argv.push(cast(void*)toStringz(ex));
850 ex = (char *)mem.malloc(e - n + 1);
851 memcpy(ex, n, e - n);
852 ex[e - n] = 0;
853 }
854 else
855 ex = (char *)"a.out"; // no extension, so give up
856 argv.push(ex);
857 global.params.exefile = ex; 854 global.params.exefile = ex;
858 } 855 }
859 856
860 // Make sure path to exe file exists 857 // Make sure path to exe file exists
861 { char *p = FileName.path(global.params.exefile); 858 { string p = FileName.path(global.params.exefile);
862 FileName.ensurePathExists(p); 859 FileName.ensurePathExists(p);
863 mem.free(p);
864 } 860 }
865 861
866 if (global.params.symdebug) 862 if (global.params.symdebug)
867 argv.push((void *)"-g"); 863 argv.push(cast(void *)cast(char*)"-g");
868 864
869 if (global.params.isX86_64) 865 if (global.params.isX86_64)
870 argv.push((void *)"-m64"); 866 argv.push(cast(void *)cast(char*)"-m64");
871 else 867 else
872 argv.push((void *)"-m32"); 868 argv.push(cast(void *)cast(char*)"-m32");
873 869
874 if (0 && global.params.exefile) 870 if (0 && global.params.exefile)
875 { 871 {
876 /* This switch enables what is known as 'smart linking' 872 /* This switch enables what is known as 'smart linking'
877 * in the Windows world, where unreferenced sections 873 * in the Windows world, where unreferenced sections
880 * Although it is documented to work with ld version 2.13, 876 * Although it is documented to work with ld version 2.13,
881 * in practice it does not, but just seems to be ignored. 877 * in practice it does not, but just seems to be ignored.
882 * Thomas Kuehne has verified that it works with ld 2.16.1. 878 * Thomas Kuehne has verified that it works with ld 2.16.1.
883 * BUG: disabled because it causes exception handling to fail 879 * BUG: disabled because it causes exception handling to fail
884 */ 880 */
885 argv.push((void *)"-Xlinker"); 881 argv.push(cast(void *)cast(char*)"-Xlinker");
886 argv.push((void *)"--gc-sections"); 882 argv.push(cast(void *)cast(char*)"--gc-sections");
887 } 883 }
888 884
889 for (i = 0; i < global.params.linkswitches.dim; i++) 885 for (i = 0; i < global.params.linkswitches.dim; i++)
890 { char *p = (char *)global.params.linkswitches.data[i]; 886 { char *p = cast(char *)global.params.linkswitches.data[i];
891 if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l')) 887 if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
892 // Don't need -Xlinker if switch starts with -l 888 // Don't need -Xlinker if switch starts with -l
893 argv.push((void *)"-Xlinker"); 889 argv.push(cast(void *)cast(char*)"-Xlinker");
894 argv.push((void *) p); 890 argv.push(cast(void *) p);
895 } 891 }
896 892
897 /* Add each library, prefixing it with "-l". 893 /* Add each library, prefixing it with "-l".
898 * The order of libraries passed is: 894 * The order of libraries passed is:
899 * 1. any libraries passed with -L command line switch 895 * 1. any libraries passed with -L command line switch
901 * 3. libraries specified by pragma(lib), which were appended 897 * 3. libraries specified by pragma(lib), which were appended
902 * to global.params.libfiles. 898 * to global.params.libfiles.
903 * 4. standard libraries. 899 * 4. standard libraries.
904 */ 900 */
905 for (i = 0; i < global.params.libfiles.dim; i++) 901 for (i = 0; i < global.params.libfiles.dim; i++)
906 { char *p = (char *)global.params.libfiles.data[i]; 902 { char *p = cast(char *)global.params.libfiles.data[i];
907 size_t plen = strlen(p); 903 size_t plen = strlen(p);
908 if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a') 904 if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a')
909 argv.push((void *)p); 905 argv.push(cast(void *)p);
910 else 906 else
911 { 907 {
912 char *s = (char *)mem.malloc(plen + 3); 908 char *s = cast(char *)malloc(plen + 3);
913 s[0] = '-'; 909 s[0] = '-';
914 s[1] = 'l'; 910 s[1] = 'l';
915 memcpy(s + 2, p, plen + 1); 911 memcpy(s + 2, p, plen + 1);
916 argv.push((void *)s); 912 argv.push(cast(void *)s);
917 } 913 }
918 } 914 }
919 915
920 /* Standard libraries must go after user specified libraries 916 /* Standard libraries must go after user specified libraries
921 * passed with -l. 917 * passed with -l.
922 */ 918 */
923 const char *libname = (global.params.symdebug) 919 const char *libname = (global.params.symdebug)
924 ? global.params.debuglibname 920 ? global.params.debuglibname
925 : global.params.defaultlibname; 921 : global.params.defaultlibname;
926 char *buf = (char *)malloc(2 + strlen(libname) + 1); 922 char *buf = cast(char *)malloc(2 + strlen(libname) + 1);
927 strcpy(buf, "-l"); 923 strcpy(buf, "-l");
928 strcpy(buf + 2, libname); 924 strcpy(buf + 2, libname);
929 argv.push((void *)buf); // turns into /usr/lib/libphobos2.a 925 argv.push(cast(void *)buf); // turns into /usr/lib/libphobos2.a
930 926
931 // argv.push((void *)"-ldruntime"); 927 // argv.push((void *)"-ldruntime");
932 argv.push((void *)"-lpthread"); 928 argv.push(cast(void *)cast(char*)"-lpthread");
933 argv.push((void *)"-lm"); 929 argv.push(cast(void *)cast(char*)"-lm");
934 930
935 if (!global.params.quiet || global.params.verbose) 931 if (!global.params.quiet || global.params.verbose)
936 { 932 {
937 // Print it 933 // Print it
938 for (i = 0; i < argv.dim; i++) 934 for (i = 0; i < argv.dim; i++)
939 printf("%s ", (char *)argv.data[i]); 935 printf("%s ", cast(char *)argv.data[i]);
940 printf("\n"); 936 printf("\n");
941 fflush(stdout); 937 fflush(stdout);
942 } 938 }
943 939
944 argv.push(null); 940 argv.push(null);
945 childpid = fork(); 941 childpid = fork();
946 if (childpid == 0) 942 if (childpid == 0)
947 { 943 {
948 execvp((char *)argv.data[0], (char **)argv.data); 944 execvp(cast(char *)argv.data[0], cast(char **)argv.data);
949 perror((char *)argv.data[0]); // failed to execute 945 perror(cast(char *)argv.data[0]); // failed to execute
950 return -1; 946 return -1;
951 } 947 }
952 948
953 waitpid(childpid, &status, 0); 949 waitpid(childpid, &status, 0);
954 950
955 status=WEXITSTATUS(status); 951 status=WEXITSTATUS(status);
956 if (status) 952 if (status)
957 printf("--- errorlevel %d\n", status); 953 printf("--- errorlevel %d\n", status);
958 return status; 954 return status;
959 +/ 955
960 } else { 956 } else {
961 writef ("Linking is not yet supported for this version of DMD.\n"); 957 writef ("Linking is not yet supported for this version of DMD.\n");
962 return -1; 958 return -1;
963 } 959 }
964 } 960 }